Tôi tin rằng có một biến trao đổi trung gian là cách thực hành tốt nhất theo cách như vậy:
update z set c1 = @c := c1, c1 = c2, c2 = @c
Đầu tiên, nó hoạt động luôn; thứ hai, nó hoạt động bất kể loại dữ liệu.
Bất chấp cả hai
update z set c1 = c1 ^ c2, c2 = c1 ^ c2, c1 = c1 ^ c2
và
update z set c1 = c1 + c2, c2 = c1 - c2, c1 = c1 - c2
Nhân tiện, chỉ hoạt động cho loại dữ liệu số và bạn có trách nhiệm ngăn chặn tràn, bạn không thể sử dụng XOR giữa đã ký và chưa ký, bạn cũng không thể sử dụng tổng cho khả năng tràn.
Và
update z set c1 = c2, c2 = @c where @c := c1
không hoạt động nếu c1 là 0 hoặc NULL hoặc chuỗi có độ dài bằng 0 hoặc chỉ khoảng trắng.
Chúng ta cần thay đổi nó thành
update z set c1 = c2, c2 = @c where if((@c := c1), true, true)
Đây là kịch bản:
mysql> create table z (c1 int, c2 int)
-> ;
Query OK, 0 rows affected (0.02 sec)
mysql> insert into z values(0, 1), (-1, 1), (pow(2, 31) - 1, pow(2, 31) - 2)
-> ;
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from z;
+------------+------------+
| c1 | c2 |
+------------+------------+
| 0 | 1 |
| -1 | 1 |
| 2147483647 | 2147483646 |
+------------+------------+
3 rows in set (0.02 sec)
mysql> update z set c1 = c1 ^ c2, c2 = c1 ^ c2, c1 = c1 ^ c2;
ERROR 1264 (22003): Out of range value for column 'c1' at row 2
mysql> update z set c1 = c1 + c2, c2 = c1 - c2, c1 = c1 - c2;
ERROR 1264 (22003): Out of range value for column 'c1' at row 3
mysql> select * from z;
+------------+------------+
| c1 | c2 |
+------------+------------+
| 0 | 1 |
| 1 | -1 |
| 2147483646 | 2147483647 |
+------------+------------+
3 rows in set (0.02 sec)
mysql> update z set c1 = c2, c2 = @c where @c := c1;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> select * from z;
+------------+------------+
| c1 | c2 |
+------------+------------+
| 0 | 1 |
| -1 | 1 |
| 2147483647 | 2147483646 |
+------------+------------+
3 rows in set (0.00 sec)
mysql> select * from z;
+------------+------------+
| c1 | c2 |
+------------+------------+
| 1 | 0 |
| 1 | -1 |
| 2147483646 | 2147483647 |
+------------+------------+
3 rows in set (0.00 sec)
mysql> update z set c1 = @c := c1, c1 = c2, c2 = @c;
Query OK, 3 rows affected (0.02 sec)
Rows matched: 3 Changed: 3 Warnings: 0
mysql> select * from z;
+------------+------------+
| c1 | c2 |
+------------+------------+
| 0 | 1 |
| -1 | 1 |
| 2147483647 | 2147483646 |
+------------+------------+
3 rows in set (0.00 sec)
mysql>update z set c1 = c2, c2 = @c where if((@c := c1), true, true);
Query OK, 3 rows affected (0.02 sec)
Rows matched: 3 Changed: 3 Warnings: 0
mysql> select * from z;
+------------+------------+
| c1 | c2 |
+------------+------------+
| 1 | 0 |
| 1 | -1 |
| 2147483646 | 2147483647 |
+------------+------------+
3 rows in set (0.00 sec)
UPDATE table SET X = Y, Y = X
là cách làm tiêu chuẩn trong SQL, chỉ có các hành vi sai trái của MySQL.