我正在使用一个作业队列,该作业队列将有许多调度程序和工作人员使用它,一些调度程序甚至尝试排队同一个作业。我想确保同样的工作没有添加,如果它已经存在"待定"状态。
该表具有代码生成的UUID的唯一ID字段。 通过名称和参数来识别不同的工作。
INSERT INTO job (id,name,parameters)
SELECT '3aa39ed8-bac8-454a-88e1-626ce6e69228', 'process_summaries', '{}'
FROM job
WHERE NOT EXISTS (
SELECT 1 FROM job
WHERE name = 'process_summaries'
AND parameters = '{}'
AND status = 'pending'
);
这会导致ID上出现重复的键错误,即使该表中的ID确实不存在。
为什么会这样?有没有办法补偿?
编辑: 因为似乎没有人相信我..,
mysql> SELECT * FROM job WHERE id='3aa39ed8-bac8-454a-88e1-626ce6e69228';
Empty set (0.00 sec)
mysql> INSERT INTO job (id,name,parameters)
-> SELECT '3aa39ed8-bac8-454a-88e1-626ce6e69228', 'process_summaries', '{}'
-> FROM job
-> WHERE NOT EXISTS (
-> SELECT 1 FROM job
-> WHERE name = 'process_summaries'
-> AND parameters = '{}'
-> AND status = 'pending'
-> );
ERROR 1062 (23000): Duplicate entry '3aa39ed8-bac8-454a-88e1-626ce6e69228' for key 'PRIMARY'
mysql> SELECT * FROM job WHERE id='3aa39ed8-bac8-454a-88e1-626ce6e69228';
Empty set (0.00 sec)
答案 0 :(得分:1)
如果子查询没有返回任何行,NOT EXISTS (...)
表达式将返回TRUE
(或1
)。在这种情况下,查询将尝试插入job
表中存在的尽可能多的行(具有相同的常量值),从而引发id
列的重复键错误。您需要更改的是从任何一行表中进行选择。在MySQL中,您可以使用FROM dual
或子查询(select 1)
。所以你的查询可能是:
INSERT INTO job (id,name,parameters)
SELECT '3aa39ed8-bac8-454a-88e1-626ce6e69228', 'process_summaries', '{}'
FROM dual
WHERE NOT EXISTS (
SELECT 1 FROM job
WHERE name = 'process_summaries'
AND parameters = '{}'
AND status = 'pending'
);
您也可以将值包装在子查询中(单行派生表):
INSERT INTO job (id,name,parameters)
SELECT *
FROM (SELECT '3aa39ed8-bac8-454a-88e1-626ce6e69228', 'process_summaries', '{}') sub
WHERE NOT EXISTS (
SELECT 1 FROM job
WHERE name = 'process_summaries'
AND parameters = '{}'
AND status = 'pending'
);