为什么这个查询
DELETE FROM test
WHERE id = ( SELECT id
FROM (SELECT * FROM test) temp
ORDER BY RAND()
LIMIT 1
);
Run Code Online (Sandbox Code Playgroud)
有时删除 1 行,有时删除 2 行,有时什么都不删除?
如果我用这种形式写:
SET @var = ( SELECT id
FROM (SELECT * FROM test) temp
ORDER BY RAND()
LIMIT 1
);
DELETE FROM test
WHERE id=@var;
Run Code Online (Sandbox Code Playgroud)
那么它可以正常工作 - 子查询有问题吗?
Rol*_*DBA 13
第一个查询不一致的原因与 MySQL 处理子查询的方式有关。事实上,子查询会经历重写和转换。
这里解释了四 (4) 个组件:
从发布的示例来看,不可能允许 item_ref 成为自我引用。就您的单个 DELETE 查询而言,整个测试表无法完全自引用自身,因为某些键在转换过程中可用,而有些则不可用。因此,当查询执行自引用时,即使实际自引用表具有键,键(在本例中为 id)也会在转换中消失。
Mysql 子查询仅适用于子 SELECT,甚至多次自引用表。对于非 SELECT 查询则不能这样说。
我希望这个解释有帮助。
我认为它没有按预期工作的原因不是 MySQL 如何处理子查询,而是 MySQL 如何处理UPDATE语句。该声明:
DELETE
FROM test
WHERE id =
( SELECT id
FROM
( SELECT *
FROM test
) temp
ORDER BY RAND()
LIMIT 1
)
Run Code Online (Sandbox Code Playgroud)
将WHERE逐行处理条件。意思是,对于每一行,它将运行子查询并针对id以下结果测试结果:
( SELECT id
FROM
( SELECT *
FROM test
) temp
ORDER BY RAND()
LIMIT 1
)
Run Code Online (Sandbox Code Playgroud)
因此,它偶尔会匹配(并删除)0、1、2 甚至更多行!
您可以像这样重写它,并且子查询将被处理一次:
DELETE t
FROM
test t
JOIN
( SELECT id
FROM test
ORDER BY RAND()
LIMIT 1
) tmp
ON tmp.id = t.id
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6805 次 |
| 最近记录: |