简体   繁体   English

SQL更新执行顺序很重要?

[英]SQL update execution order matters?

I was always of the understanding that during a SQL UPDATE the existing values would remain until the entire update statement was complete, but I am seeing different behaviour in practice. 我一直认为在SQL UPDATE期间,现有值将保持不变,直到整个更新语句完成,但我在实践中看到不同的行为。

Inventory
-----------------------------
date        base  flexible
2014-05-01  5     10
2014-05-02  5     10

UPDATE Inventory SET base = GREATEST(0, base - 7), flexible = flexible - GREATEST(0, (7 - base)) WHERE date = '2014-05-01'

UPDATE Inventory SET flexible = flexible - GREATEST(0, (7 - base)), base = GREATEST(0, base - 7) WHERE date = '2014-05-02'

Inventory
-----------------------------
date        base  flexible
2014-05-01  0     3
2014-05-02  0     8

In the first example it seems that base is updated to zero with the first expression, causing the second expression to evaluate incorrectly (7 - 0) instead of (7 - 5) . 在第一个示例中,似乎使用第一个表达式将base更新为零,导致第二个表达式不正确地计算(7 - 0)而不是(7 - 5)

Can anyone explain what is going on here? 谁能解释一下这里发生了什么?

MySQL breaks the standard a bit; MySQL打破了标准;

It updates columns using the current field value considering the field order in the update instead of following the SQL standard which uses the field value from before the update statement. 它使用当前字段值更新列,考虑更新中的字段顺序,而不是遵循使用更新语句之前的字段值的SQL标准。

From the docs ; 来自文档 ;

If you access a column from the table to be updated in an expression, UPDATE uses the current value of the column. 如果从表中访问要在表达式中更新的列,UPDATE将使用列的当前值。 The second assignment in the following statement sets col2 to the current (updated) col1 value, not the original col1 value. 以下语句中的第二个赋值将col2设置为当前(更新的)col1值,而不是原始col1值。 The result is that col1 and col2 have the same value. 结果是col1和col2具有相同的值。 This behavior differs from standard SQL. 此行为与标准SQL不同。

UPDATE t1 SET col1 = col1 + 1, col2 = col1; UPDATE t1 SET col1 = col1 + 1,col2 = col1;

您将在提交之前看到自己的更改,而其他人则不会。

Take a look on this . 看看这个 I think it is because of GREATEST function... 我认为这是因为GREATEST功能......

How about storing base value in user variables, like this: 如何将base值存储在用户变量中,如下所示:

UPDATE Inventory
SET base = (@base := base), flexible = (@flexible := flexible),
    base = GREATEST(0, @base - 7),
    flexible = @flexible - GREATEST(0, (7 - @base));

Here are tests: 这是测试:

mysql> insert into Inventory values('2014-05-01', 5, 10);
Query OK, 1 row affected (0.00 sec)

mysql> insert into Inventory values('2014-05-02', 5, 10);
Query OK, 1 row affected (0.00 sec)

mysql>
mysql>     UPDATE Inventory
    ->     SET base = (@base := base), flexible = (@flexible := flexible),
    ->         base = GREATEST(0, @base - 7),
    ->         flexible = @flexible - GREATEST(0, (7 - @base));
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0

mysql> SELECT * FROM Inventory;
+------------+------+----------+
| date       | base | flexible |
+------------+------+----------+
| 2014-05-01 |    0 |        8 |
| 2014-05-02 |    0 |        8 |
+------------+------+----------+
2 rows in set (0.00 sec)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM