![](/img/trans.png)
[英]Why my MySQL statement doesn't return any records when the where clause with ALL returns true?
[英]why my `delete where id in` statement drop all records in the table?
我正在使用 MySQL 版本 5.7.24。 我想删除回复表中具有相同 ex_id 和 ex_type 的记录:
CREATE TABLE `reply` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`content` varchar(1024) NOT NULL,
`ex_id` bigint(20) DEFAULT '0',
`ex_type` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_ex_id_type` (`ex_id`,`ex_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
有以下数据:
+----+-------------------+-------+---------+
| id | content | ex_id | ex_type |
+----+-------------------+-------+---------+
| 1 | this is a content | 1 | 1 |
| 2 | this a test | 2 | 1 |
| 3 | this a contet | 1 | 1 |
| 4 | the 4th content | 3 | 1 |
+----+-------------------+-------+---------+
记录 1 和 3 共享相同的 ex_id 和 ex_type,其中我想删除具有较小 id 的记录(记录 1),所以我编写了以下查询:
delete from reply where id in (
select id from (
select min(id) from reply group by ex_type and ex_id having count(1) > 1
) tmp
)
-- Query OK, 4 rows affected
这应该删除一条记录,但所有记录都被删除。
Actually there is a mistake in this SQL, the inner SQL select min(id) from reply group by ex_type and ex_id having count(1) > 1
return the result with only field: 'min(id)', outer sql select id from () tmp
选择了一个不存在的字段 id 导致错误,但是 MySQL 仍然执行这个 sql 并删除所有记录。
我想知道为什么会这样。
您的查询在逻辑上是错误的。
这部分:
select min(id) from reply group by ex_type and ex_id having count(1) > 1
按ex_type and ex_id
而不是ex_type, ex_id
。
最重要的是,它不会返回名为/别名为id
的列。
以便:
select id from...
实际上是指表的id
,返回表的所有id
,结果就是所有的行都被删除了。
您可以在此处查看此行为。
我相信这是你想要做的:
delete from reply where id in
(
select id from (
select min(id) id from reply group by ex_type, ex_id having count(*) > 1
) tmp
);
...outer sql
select id from () tmp
a non exsit field id which lead to an error, but mysql execute this sql and delete all records.我想知道为什么会这样。
此子查询不会自行运行:
select id from (
select min(id) from reply group by ex_type and ex_id having count(1) > 1
) tmp
/* SQL Error (1054): Unknown column 'id' in 'field list' */
但是当它在子查询中运行时,根据 scope 解析规则,id 列解析为外部查询的 id 列,因为请求的列不存在于 FROM 子句中。 查询本质上是这样的:
delete from reply where id in (
select reply.id from (
select min(id) from reply group by ex_type and ex_id having count(1) > 1
) tmp
)
/* Affected rows: 4 Found rows: 0 Warnings: 0 Duration for 1 query: 0.031 sec. */
该条件对所有行都为真,因为 1 IN (1)、2 IN (2)、3 IN (3)... 都为真。 修复错字( group by ex_type and ex_id
)不会解决问题,请将您的查询更改为:
delete from reply where id in (
select tmp.id from (
select min(id) as id from reply group by ex_type, ex_id having count(1) > 1
) tmp
)
有趣 - 这似乎是一个错误,因为 DELETE 在这种情况下应该失败!
无论如何,只需将别名附加到 min(id) (并在 GROUP BY 之前删除那个奇怪的“和”),一切都会好起来的......(虽然,我不会这样写这个查询)
DROP TABLE IF EXISTS reply;
CREATE TABLE `reply` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`content` varchar(1024) NOT NULL,
`ex_id` bigint(20) DEFAULT '0',
`ex_type` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_ex_id_type` (`ex_id`,`ex_type`)
);
INSERT INTO reply VALUES
(1,'this is a content',1,1),
(2,'this a test',2,1),
(3,'this a contet',1,1),
(4,'the 4th content',3,1);
delete from reply where id in
(
select id from (
select min(id) id from reply group by ex_type, ex_id having count(1) > 1
) tmp
);
SELECT * FROM reply;
+----+-----------------+-------+---------+
| id | content | ex_id | ex_type |
+----+-----------------+-------+---------+
| 2 | this a test | 2 | 1 |
| 3 | this a contet | 1 | 1 |
| 4 | the 4th content | 3 | 1 |
+----+-----------------+-------+---------+
FWIW,对于一个小数据集,我可能会这样写那个查询......
DELETE r
FROM reply r
JOIN
( SELECT MIN(id) id
FROM reply
GROUP
BY ex_type
, ex_id
HAVING COUNT(0) > 1
) x
ON x.id = r.id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.