目的
MariaDB,PostgreSQLのUPDATE文の挙動の違いを見る
環境
OS:Ubuntu14.04
DB:MariaDB 10.0.11 InnoDB、 PostgreSQL 9.3.5
thinkpad T440p
テーブルとデータ
CREATE TABLE IF NOT EXISTS hoge(
id SERIAL,
col1 INT NOT NULL DEFAULT 0,
col2 INT NOT NULL DEFAULT 0,
col3 INT NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
INSERT IGNORE INTO hoge (col1,col2,col3) VALUES (1,10,100);
PostgreSQL
test=# select * from hoge;
id | col1 | col2 | col3
----+------+------+------
1 | 1 | 10 | 100
(1 row)
test=# BEGIN;
BEGIN
test=# UPDATE hoge SET col1=col1+1,col2=col1+col2,col3=col2+col3;
UPDATE 1
test=# select * from hoge;
id | col1 | col2 | col3
----+------+------+------
1 | 2 | 11 | 110
(1 row)
test=# ROLLBACK;
ROLLBACK
MariaDB
MariaDB [test]> select * from hoge;
+----+------+------+------+
| id | col1 | col2 | col3 |
+----+------+------+------+
| 1 | 1 | 10 | 100 |
+----+------+------+------+
1 row in set (0.00 sec)
MariaDB [test]>
MariaDB [test]> BEGIN;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> update hoge set col1=col1+1, col2=col1+col2, col3=col2+col3;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [test]> select * from hoge;
+----+------+------+------+
| id | col1 | col2 | col3 |
+----+------+------+------+
| 1 | 2 | 12 | 112 |
+----+------+------+------+
1 row in set (0.00 sec)
MariaDB [test]> ROLLBACK;
Query OK, 0 rows affected (0.02 sec)
結果
PostgreSQLはupdateを評価する際に自身の更新が見えないようになっているのに対して
MariaDBでは左から右へ評価されているので結果が異なります。
SQL92の13.10では「6) The value expressions are effectively evaluated for each row of T before updating any row of T.」と書かれているのでPostgreSQLのほうが標準SQLの動作と一致しています。
http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
MySQLでも「Single-table UPDATE assignments are generally evaluated from left to right. This behavior differs from standard SQL. 」と書かれているのでMariaDBと同様の結果になります
http://dev.mysql.com/doc/refman/5.6/en/update.html