0

INSERT IGNORE不起作用,因为实际上不会有关键冲突。

这是一个进度队列。对于一个应用程序,我不想要两行状态S(对于“已启动”)。但是其他应用程序应该能够 - 特别是如果我想强制两个工作项同时发生,我可以。这就是为什么它不是数据库约束的原因。

所以在 SQL 中说“插入不存在的地方”有点棘手。这有效:

insert into user_queue_google
(user_id, status, start_timestamp)
(select 221, 'S', NOW() FROM filter_type
WHERE 221 not in (select user_id from user_queue_google where status = 'S') limit 1);

问题是filter_type一个完全不相关的表,我只知道它很小并且恰好永远不会为空。如果由于某种原因它是空的,这将失败。

如果不使用 SQL 程序中的存储程序或 IF/THEN 逻辑,我能否避免这种非常可怕的黑客攻击?

4

3 回答 3

0

这应该有效:

insert into user_queue_google
(user_id, status, start_timestamp)
select
    A.user_id,
    A.status,
    A.start_timestamp
FROM
  (SELECT
     221 user_id, 
     'S' status, 
     NOW() start_timestamp) AS A
  LEFT JOIN user_queue_google ON A.user_id = user_queue_google.user_id AND A.status = user_queue_google.status
WHERE
   user_queue_google.user_id IS NULL;

如果行不存在,请参阅附加的小提琴插入

于 2013-10-03T16:25:11.310 回答
0

使用dual系统虚拟表

insert into user_queue_google (user_id, status, start_timestamp)
select 221, 'S', NOW()
from dual
WHERE not exists 
(
   select user_id 
   from user_queue_google 
   where status = 'S' 
   and user_id = 221
)

在没有引用表的情况下,您可以将 DUAL 指定为虚拟表名

资源

于 2013-10-03T15:33:56.537 回答
0

您需要有一个UNIQUE索引INSERT IGNORE才能有效地工作。您可以做的是添加一个默认为无害但可以更改为唯一键的附加列:

CREATE UNIQUE INDEX index_block ON user_queue_google (user_id, force);

设置force为具有DEFAULT 0. 如果要强制两个作业同时运行,请将其设置为其他内容以避免冲突:

UPDATE user_queue_google SET status='S', force=UNIX_TIMESTAMP() WHERE user_id=221

这将腾出一个新的插槽来插入新的工作。

于 2013-10-03T15:37:01.257 回答