Please answer these questions before submitting your issue. Thanks!
drop table if exists t1, t2;
create table t1 (c_str varchar(40));
create table t2 (c_str varchar(40));
insert into t1 values ('Alice');
insert into t2 values ('Bob');
select t1.c_str, t2.c_str from t1, t2 where t1.c_str <= t2.c_str;
update t1, t2 set t1.c_str = t2.c_str, t2.c_str = t1.c_str where t1.c_str <= t2.c_str;
select t1.c_str, t2.c_str from t1, t2 where t1.c_str <= t2.c_str;
The values of t1.c_str and t2.c_str should be swapped in the above case, that is, the last selection should return an empty set.
mysql> select t1.c_str, t2.c_str from t1, t2 where t1.c_str <= t2.c_str;
+-------+-------+
| c_str | c_str |
+-------+-------+
| Alice | Bob |
+-------+-------+
1 row in set (0.06 sec)
mysql> update t1, t2 set t1.c_str = t2.c_str, t2.c_str = t1.c_str where t1.c_str <= t2.c_str;
Query OK, 1 row affected (0.06 sec)
Rows matched: 2 Changed: 1 Warnings: 0
mysql> select t1.c_str, t2.c_str from t1, t2 where t1.c_str <= t2.c_str;
+-------+-------+
| c_str | c_str |
+-------+-------+
| Bob | Bob |
+-------+-------+
1 row in set (0.05 sec)
master @ 8978773f5e3d43a100550e6babea9904a99e5938
release-4.0 @ 3948c7ba7b5d4a081abf2162b791ab67fe650882
/assign @zz-jason
The MySQL behavior is explained in link, TiDB implementation is different from MySQL.
MySQL behaviors are different for single and multiple tables, the TiDB behavior is more reasonable, I think we can document about this.
I believe the SQL standards do talk about what the correct behavior is here. I am not sure if MySQL is necessarily correct, but if TiDB differs, it should be defendable if it is at least standard.
I verify this in mysql version 8.0.19, it actually swaps two values from different tables. Should TiDB have the same behavior? @SunRunAway @cfzjywxk @nullnotnil
mysql> drop table if exists t1, t2;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
mysql> create table t1 (c_str varchar(40));
Query OK, 0 rows affected (0.01 sec)
mysql> create table t2 (c_str varchar(40));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values ('Alice');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t2 values ('Bob');
Query OK, 1 row affected (0.00 sec)
mysql> select t1.c_str, t2.c_str from t1, t2 where t1.c_str <= t2.c_str;
+-------+-------+
| c_str | c_str |
+-------+-------+
| Alice | Bob |
+-------+-------+
1 row in set (0.00 sec)
mysql> update t1, t2 set t1.c_str = t2.c_str, t2.c_str = t1.c_str where t1.c_str <= t2.c_str;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> select t1.c_str, t2.c_str from t1, t2 where t1.c_str <= t2.c_str;
Empty set (0.00 sec)
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.19 |
+-----------+
1 row in set (0.00 sec)
responsed from Mysql comminuty
https://bugs.mysql.com/bug.php?id=100527&thanks=2¬ify=67
@cfzjywxk @nullnotnil @SunRunAway
So we should recovery the behavior.
I tried on SQLite3
sqlite> create table t(a int, b int);
sqlite> insert into t values(1, 2);
sqlite> select * from t;
1|2
sqlite> update t set a=b, b=a;
sqlite> select * from t;
2|1
PG
test=# create table t (a int, b int);
CREATE TABLE
test=# insert into t values (1,3);
INSERT 0 1
test=# select * from t;
1 | 3
test=# update t set a=b, b=a;
UPDATE 1
test=# select * from t;
3 | 1
PG does not supprot update more than one tables in one statement:
test=# update t1, t2 set t1.a=t2.a, t2.a=t1.a;
ERROR: syntax error at or near ","
LINE 1: update t1, t2 set t1.a=t2.a, t2.a=t1.a;
compared Mysql to Oracle, PG and sqlLite, only mysql does not support swaping two columns. We can verify this on http://sqlfiddle.com/#!4/794de/1/0
https://bugs.mysql.com/bug.php?id=100527&thanks=2¬ify=67
@cfzjywxk @nullnotnil @SunRunAway
So we should recovery the behavior.
I think it is better to have the standard behavior here.
If it turns out users depend on the (incorrect) MySQL behavior, we can add an option to permit this behavior. But to keep the options to a minimum: change it first, add the option if it becomes required.
I think it is better to have the standard behavior here.
change it first, add the option if it becomes required.
Agree. Let's resolve this issue as @nullnotnil said. That is, TiDB swaps two values from one table if the query is update t set t.a=t.b, t.b=t.a;
cc @cfzjywxk, @lzmhhh123, @fzhedu
/cc @dyzsr
/assign
Note: Make Sure that 'component', and 'severity' labels are added
Example for how to fill out the template: https://github.com/pingcap/tidb/issues/20100
Most helpful comment
compared Mysql to Oracle, PG and sqlLite, only mysql does not support swaping two columns. We can verify this on http://sqlfiddle.com/#!4/794de/1/0