Mysql inserts in the middle instead at the end of table - mysql

I am new to database. I deleted few rows (till end of table) from a database table. Now every time i execute INSERT query via php, it inserts new row immediately after last deleted row and pushes the previous inserts down by one row.
As shown in above figure, the rows are deleted from 2019-08-18 (red rectangle) via the query:
DELETE FROM mytable WHERE date > '2019-08-18'
Now new inserts have wrong order as shown in green rectangle in above figure. Though the row with date 2019-08-19 is inserted first, it is pushed to the end of table.
What am i doing wrong?

Most relational databases will not return the rows in any particular order unless you ask explicitly. They'll just do whatever's easiest. Often that's insertion order, or maybe order on disk, or whatever index was last used. It's really arbitrary and may even change from version to version of the same database platform.
"If you cared you'd ask" is the principle at work here. You didn't ask, so MySQL presumes you don't care.
Add an ORDER BY clause to get predictable orders. Otherwise be prepared for the unexpected.

Related

Best practice for handling positions of rows

What is the best practice for moving rows. So that you might want to change order of items. Now if you make a new column called order_id or something, wouldn't that fail if I delete or select rows.
Another method I guess is to just switch values completely with an primary ID, so just values except the ID are changed. however I do not know what people usually use. There are so many websites that give you the ability to change order of things.how so they do that?
Every SQL statement that returns a visible result set should include an ORDER BY clause so that the results are consistent. The Standard does not guarantee that the order of rows in a particular table will remain constant or consistent, even if obvious changes aren't made to the table.
What you use for your ORDER BY clause depends on the use case. A date value is the usual choice for a comment thread or blog entry ordering. However, if you want the user to be able to customize the order that a result set shows in, then you have to provide a column that represents the position of the row, and adjust the value of that column when the user makes changes to the order they see.
For example, if you decide that the column will contain a sequential number, starting with 1 for the first row, 2 for the second, etc. then you will be ok to delete rows when they need to be deleted without having to do updates. However, if you insert a row, you will need to give the row you insert the sequential number appropriate for it's position, and update all rows below that with their new position. Same goes for if you move a row from somewhere else to a new location; the rows between the new and old locations need to be updated with new postion indexes.

tracking actual changes in rows when updating table

I have a table which i keep on updating, from the values of other source in my code. The value I update may or may not be same as the value already in the row.
I need some kind of algorithm may be via mysql (db) or otherwise (part of code) so that I later may be able to identify which rows have a changed value.
There is a date modified column which I change. But that will not be a true indicator as it will always be updated. I want a way by which I can determine whether some predefined columns have changed values,
One solution is this: I can do a select query, then compare and update a changed flag in the table. But that seems complex and not for me as I have a table with a lot of records
Another solution might be to save the md5 checksum of the values in a column and while updating compare the previous md5 and current md5 and so on.
I want to know the best solution.
There's a fairly simple way to handle this problem. Let's think of it as managing when a row's timestamp gets updated.
First of all, as I'm sure you know, your table needs a timestamp column with default settings for INSERT and UPDATE. That looks like this if the column is called ts.
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Second, you can use an UPDATE query like this to change the values in a row.
UPDATE stock
SET val1 = 'newval1',
val2 = 'newval2',
changed_by = 'current_user_id'
WHERE id = 'id_to_change'
AND NOT (val1 == 'newval1' AND val2 == 'newval2')
The AND NOT clause on the WHERE will prevent the update from taking place unless 'newval1' or 'newval2' would actually provide new values. This works because no rows match the WHERE clause in the update.
When the update is prevented from taking place your automatically set ts column will not change. Neither will the changed_by column be set to the present user's user_id. So, you have the time and user of the most recent genuine change.
Also, many host language interfaces to MySQL have a method call to determine how many rows were affected by a recent UPDATE operation. With this technique, you'll get back zero rows when the row is not updated. That might be convenient for your user interface.
Also, this technique uses a single query, so it's safe if more than one user is trying to update the same row at the same time. There's no need to use a transaction to guarantee that.
(Note that tracking the changed_by user is optional, and will only work if your application can provide the current user's actual id.)
This is reasonably efficient as long as the database search for WHERE id = 'id_to_change' works quickly.
It does require reworking your application's UPDATE queries. But so would any other approach to this problem.

order and change one column of database

I have one col in my database named position used for ordering. However, when some records is deleted, the sequence get messed up. I want to reorder this col when the table is changed(maybe use trigger).
position(old) -> position(new)
1 1
3 2
7 3
8 4
like this.
I think there will not exist equal number even in position(old), because I have already attach some function in PHP to reorder the column when updates occurs. However, when a record is deleted because of the deletion of its parent, function will not be called.
Thanks for help!
If you are using the column just for ordering, you do not need to update column on deletion, because the order will still be correct. And you will save some resources.
But if you really need to update by sequence, look at this answer:
updating columns with a sequence number mysql
I believe (as scrowler wrote) the better way in such case is to update rows from the application, after application deletes the parent record.
If you decide to update it in the application then...
If position = n is deleted, you logic should be set position = position - 1 where position > n
Please note that this will work only if you delete one record at a time from your application and before assuming that before the delete is triggered the data is already in sequence

Mysql duplicate rows (ignore id + timestamp) without naming all other columns in the query?

I have tried to make this question concise in the title.
There are many answers to similar questions, but all involve naming every column in the table in the query.
What I want is a query to show me duplicate rows, but to ignore one or two columns, and I would like to be able to do it like shown in this post Return duplicate records, but without having to explicitly name every column in the table.
Is it possible?
Note: Being that this is the top google result for 'workbench how to duplicate a row' I feel inclined to provide an answer for that question. If a moderator feels this is inappropriate; feel free to help resolve the inappropriation.
Select all columns (or your target columns) from a single table, without joins or anything else that restricts in-editor inserts.
Eg: SELECT * FROM mytable ORDER BY id DESC
right-click on the row you want to copy, Copy Row
Go to the bottom of the select results, end, there should be a line with all null's
right-click on the null'ed row, Paste Row
Don't forget to nullify, or set to be the default, any columns you want to keep; like the primary index/id, or any unique constrained columns!
To insert your duplicated row use the Apply button on the lower right.
Workbench will open a dialog and show your the generated insert statements and offer to execute them for you. Permitting there are no errors you have just duplicated a row!
Run your select statement again to see your results.
I don't think there is another way. I would right-click on the table in MySQL Workbench, select "Send to SQL Editor" and "Select All Statement" as a starting point.

Select only recent updated rows in MySQL db with a large data volume

I'm working with a InnoDB table that contains up to 30000 records. Rows are updated frequenty with stock_quantity value. What i need to do is to select only the most recent updated rows with a scheduled task and perform some actions thru a WebService.
Just trying to understand which is the best way for doing this without kill performance. I'm thinking at 3 different solution:
using a datetime column and update its value on each modify. Then select rows where date_col > NOW()-20 min. (20 min. is the frequency crontab is running)
using a boolean column and set the value to true each time the row is modified. Then select rows where boolean_col is true. If the task is executed set back the value of boolean_col to false.
using a second table to store recent updated columns. On each update of a row in table_1 copy the row to table_2. Then select all rows from table_2, perform actions and truncate table_2.
Anyway I'm pretty sure the right solution is not listed up there... so does anyone have some good advice? Thanks.
fist at all,
30,000 record is not that big ...
i prefer method 1 with some additional changes
set the datetime column default to on update current_timestamp
build an index of this column
method 2 will incurred redundant write, and read
method 3 is the worse, it almost double x double the write and read operations
I would personally use your option 2.
I would seriously look at a tigger to set the value to 1 if the row is edited. Of course excluding and update that only effect the boolean col.
I would then have the cron search the table when boolean = 1, return the list process the file and update the field back to 0 once complete.
This would be my approach, but like you said there might be a better way.
Another Idea: You might also want to look at replacing your cron with the tigger and preform the action your cron does on record update might work...