Mysql update statement updated Unexpectedly - mysql

For updating MySql table, i used the query-
update TABLE set status=1 and finalStatus_id=1 and id in (1,3,4);
I mistakenly wrote and in place of where and execute the query.
As per query, I was expecting ERROR but it ran successfully. Secondly, I was expected to update status of all rows as 1.
But,
Status of all the rows got updated to 0.(Why this?)
I tried to find out the reason and smililar use of query but cant find.
Why is this? Why it behaved like this?

Your code is interpreted as:
update TABLE
set status = (1 and (finalStatus_id = 1) and (id in (1, 3, 4));
This is a boolean expression. It will only be "1" (true) when the id is 1, 3, or 4 and the value of finalStatus_id is 1. If all rows are set to 0, then this is never true.
The query you want is presumably:
update TABLE
set status = 1,
finalStatus_id = 1
where id in (1, 3, 4);
Commas are used to separate the updates to separate columns, not the boolean and.

In SQL, the WHERE clause is optional. It's legal syntax to update every row in the table, which you can do by omitting the WHERE clause.
UPDATE table SET status=1;
Maybe this is not a good language design, to make the default be that your update will apply to every row, but this standard SQL syntax, for better or worse.
The MySQL client has a flag --safe-updates which prevents you from executing such queries by accident. It treats a query as an error if it's an UPDATE or DELETE and has no WHERE clause. This only works in the MySQL client, not in any programmatic interface. So it doesn't work if you make the same mistake in application code.
The next part is that you set your status to an expression. An expression can be a simple value like 1, but it can also be a more complex expression.
This is a legal expression:
1 and finalStatus_id=1 and id in (1,3,4)
Since 1 is the same thing as true, it's a legal operand for and. The other two terms are also boolean conditions.
The result of the whole expressions is a boolean true or false, which in MySQL is equivalent to 1 or 0.
So you applied this expression to every row in your table. Certainly it will be false on every row where id is not in (1,3,4).

Related

MySQL update returns 0 rows affected while select returns results

select * from t_circle
where status = 0 and author_phone = 13511111111
and id in (
1,
2,
3
)
;
returns 3 rows with status of 0.
But the following update query with same conditions returns 0 rows affected:
udpate t_circle set status = 2
where status = 0 and author_phone = 13511111111
and id in (
1,
2,
3
);
Is there a reason for this? I have tried start transaction and commit, but still 0 rows affected. Other questions' answers suggest to run select first and make sure the rows are changed since if new value == old value, it is considered affected. I have excluded these 2 possibilities.
Note: this issue is found in our production server(Yeah I know I shouldn't but I have to) with InnoDB engine. I could modify the contents in GUI client like DBeaver and click save and the changes take effect, but not with sql statements. I wonder if it has anything to do with my account authorization?
Resolved! It is because I misspelled UPDATE. When I use mysql> in command line, update with 'udpate' just gives Query OK, 0 rows affected. My mysql's version is 5.7
I know that there is something wrong with the user permission of your client
By comparing GUI generated sql queries when I change something in GUI and my own queries. I found out the reason is I misspelled update to udpate. Now I begin to wonder how could mysql not complain about syntax error and just returns with 0 rows affected?
Well, at least now I know what to do when something odd happens.

SELECT & UPDATE at the same time - race condition

I'm experiencing a race condition because I'm dealing with a lot of concurrency.
I'm trying to combine these two mysql statements to execute at the same time.
I need to select a row and update the same one...
SELECT id_file FROM filenames WHERE pending=1 LIMIT 1;
UPDATE filenames SET pending=2 WHERE id_file=**id of select query**;
Another solution to the race-condition I'm experiencing would be to perform an UPDATE query where pending=1 and somehow get the ID of the updated row, but I'm not sure if that's even possible?
Thanks
To deal with concurrency is one of the basic functions of transactions.
Wrap your queries into one transaction and tell the DBMS, that you need the row not to change in between with FOR UPDATE:
BEGIN;
SELECT id_file FROM filenames WHERE pending=1 LIMIT 1 FOR UPDATE;
# do whatever you like
UPDATE filenames SET pending=2 WHERE id_file=**id of select query**;
COMMIT;
You can execute these statements with 4 mysqli_query calls, and do whatever you want in between, without need to worry about the consistency of your database. The selected row is save until you release it.
You can avoid the "race" condition by performing just an UPDATE statement on the table, allow that to identify the row to modified, and then subsequently retrieve values of columns from the row.
There's a "trick" returning values of columns, in your case, the value of the id_file column from the row that was just updated. You can use either the LAST_INSERT_ID() function (only if the column is integer type), or a MySQL user-defined variable.
If the value of the column you want to retrieve is integer, you can use LAST_INSERT_ID() function (which supports a BIGINT-64 value).
For example:
UPDATE filenames
SET pending = 2
, id_file = LAST_INSERT_ID(id_file)
WHERE pending = 1
LIMIT 1;
Following the successful execution of the UPDATE statement, you'll want to verify that at least one row was affected. (If any rows satisfied the WHERE, and the statement succeeded, we know that one row will be affected. Then you can retrieve that value, in the same session:
SELECT LAST_INSERT_ID();
to retrieve the value of id_file column of the last row processed by the UPDATE statement. Note that if the UPDATE processes multiple rows, only the value of last row that was processed by the UPDATE will be available. (But that won't be an issue for you, since there's a LIMIT 1 clause.)
Again, you'll want to ensure that a row was actually updated, before you rely on the value returned by the LAST_INSERT_ID() function.
For non-integer columns, you can use a MySQL user-defined variable in a similar way, assigning the value of the column to a user-defined variable, and then immediately retrieve the value stored in the user-defined variable.
-- initialize user-defined variable, to "clear" any previous value
SELECT #id_file := NULL;
-- save value of id_file column into user-defined variable
UPDATE filenames
SET pending = 2
, id_file = (SELECT #id_file := id_file)
WHERE pending = 1
LIMIT 1;
-- retrieve value stored in user-defined variable
SELECT #id_file;
Note that the value of this variable is maintained within the session. If the UPDATE statement doesn't find any rows that satisfy the predicate (WHERE clause), the value of the user-defined variable will be unaffected... so, to make sure you don't inadvertently get an "old" value, you may want to first initialize that variable with a NULL.
Note that it's important that a subsequently fired trigger doesn't modify the value of that user defined variable. (The user-defined variable is "in scope" in the current session.)
It's also possible to do the assignment to the user-defined variable within in a trigger, but I'm not going to demonstrate that, and I would not recommend you do it in a trigger.

Check if record exists delete it using mysql

i'm using MySQL and i want to check if a record exists and if it exists delete this record.
i try this but it 's not working for me:
SELECT 'Barcelone' AS City, EXISTS(SELECT 1 FROM mytable WHERE City = 'Barcelone') AS 'exists';
THEN
DELETE FROM mytable
WHERE City = 'Barcelone';
Thank you for your help.
The if statement is only allowed in stored procedures, stored functions, and triggers (in MySQL).
If I understand what you want, just do:
DELETE FROM mytable
WHERE City = 'Barcelone';
There is no reason to check for the existence beforehand. Just delete the row. If none exist, no problem. No errors.
I would recommend an index on mytable(city) for performance reasons. If you want to check if the row exists first, that is fine, but it is unnecessary for the delete.
If you mean MySQL is returning an error message (if that's what you mean by "not working for me"), then that's exactly the behavior we would expect.
That SQL syntax is not valid for MySQL.
If you want to delete rows from a table, issue a DELETE statement, e.g.
DELETE FROM mytable WHERE City = 'Barcelone'
If you want to know how many rows were deleted (if the statement doesn't throw an error), immediately follow the DELETE statement (in the same session) with a query:
SELECT ROW_COUNT()
Or the appropriate function in whatever client library you are using.
If the ROW_COUNT() function returns 0, then there were no rows deleted.
There's really no point (in terms of MySQL) in issuing a SELECT to find out if there are rows to be deleted; the DELETE statement itself will figure it out.
If for some reason your use case requires you to check whether there are rows be be deleted, then just run a separate SELECT:
SELECT COUNT(1) FROM mytable WHERE City = 'Barcelone'

What is happening when you run the query "SELECT * FROM table_name WHERE column_name;"?

I have a database table with several columns. One of the columns is intended to be used as a boolean setup as TINYINT(1) DEFAULT 0.
I accidentally discovered that if you run this query
SELECT * FROM table_name WHERE column_name;
it returns the rows that have column_name = 1.
I am curious to know the logic that MySql is using to process this query.
As the documentation says in "Select Syntax", (http://dev.mysql.com/doc/refman/5.1/en/select.html)
where_condition is an expression that evaluates to true for each row to be selected
So the simple column name is evaluated as a boolean and the corresponding rows are selected. You'll find it works for ints, too.

How to select and update a record at the same time in mySQL?

Is there any way to select a record and update it in a single query?
I tried this:
UPDATE arrc_Voucher
SET ActivatedDT = now()
WHERE (SELECT VoucherNbr, VoucherID
FROM arrc_Voucher
WHERE ActivatedDT IS NULL
AND BalanceInit IS NULL
AND TypeFlag = 'V'
LIMIT 1 )
which I hoped would run the select query and grab the first record that matches the where clause, the update the ActivatedDT field in that record, but I got the following error:
1241 - Operand should contain 1 column(s)
Any ideas?
How about:
UPDATE arrc_Voucher
SET ActivatedDT = NOW()
WHERE ActivatedDT IS NULL
AND BalanceInit IS NULL
AND TypeFlag = 'V'
LIMIT 1;
From the MySQL API documentation :
UPDATE returns the number of rows that were actually changed
You cannot select a row and update it at the same time, you will need to perform two queries to achieve it; fetch your record, then update it.
If you are worrying about concurrent processes accessing the same row through some kind of race condition (supposing your use case involve high traffic), you may consider other alternatives such as locking the table (note that other processes will need to recover--retry--if the table is locked while accessing it)
Or if you can create stored procedure, you may want to read this article or the MySQL API documentation.
But about 99% of the time, this is not necessary and the two queries will execute without any problem.