【发布时间】:2021-10-11 11:43:29
【问题描述】:
我有一个包含 2 列的 mysql8 表:ID(Int) AND UUID(Varchar36):
CREATE TABLE `upsert_test` (
`ID` int unsigned DEFAULT NULL COMMENT 'id;',
`UUID` varchar(36) DEFAULT NULL
) ENGINE=InnoDB;
我需要在没有唯一索引的情况下模仿upsert 的行为,最后我得到了以下 sql 命令,它适用于 mysql 5.7:
INSERT INTO upsert_test
SELECT 1 AS ID, UUID() AS "UUID"
FROM upsert_test
WHERE ID=1
HAVING COUNT(*)=0;
但是升级到mysql8.0后,只插入了一个空UUID,如流:
mysql> SELECT * FROM upsert_test;
+------+------+
| ID | UUID |
+------+------+
| 1 | NULL |
+------+------+
1 row in set (0.00 sec)
如果我执行select 子命令,我会得到一个有效的 UUID(这个查询实际上是在插入任何数据之前执行的):
mysql> SELECT 1 AS ID, UUID() AS "UUID"
-> FROM upsert_test
-> WHERE ID=1
-> HAVING COUNT(*)=0;
+----+--------------------------------------+
| ID | UUID |
+----+--------------------------------------+
| 1 | a1fbea94-f6c4-11eb-903c-0242ac110002 |
+----+--------------------------------------+
1 row in set (0.00 sec)
而且它就是无法插入。
如果我忽略 HAVING 部分:
mysql> INSERT INTO upsert_test
-> SELECT 2 AS ID, UUID() AS "UUID";
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM upsert_test;
+------+--------------------------------------+
| ID | UUID |
+------+--------------------------------------+
| 1 | NULL |
| 2 | 033e03f7-f6c5-11eb-903c-0242ac110002 |
+------+--------------------------------------+
2 rows in set (0.00 sec)
我们可以看到插入了一个有效的 UUID。
我整个下午都在为这个问题苦苦挣扎,只是无法弄清楚问题是什么。
【问题讨论】:
-
似乎您已经有一个列,所以
HAVING COUNT(*)=0将阻止插入。试试HAVING COUNT(*)=1 -
我试过
HAVING COUNT(*)=1,但我认为这不是问题所在。新行确实插入没有失败(因为执行插入命令之前表中没有数据),但是插入的UUID是NULL。 -
WHERE ID=1 HAVING COUNT(*) = 0;部分的预期用途是什么? -
我需要
upsert数据(如果ID=1所在的行存在,则不应插入新行),由于某些原因我无法使用unique-index(唯一索引列中会有空值)。 @mechanical_meat