为什么我的 `delete where id in` 语句会删除 table 中的所有记录?
why my `delete where id in` statement drop all records in the table?
我正在使用 MySQL 版本 5.7.24。我想删除具有相同 ex_id 和 ex_type 的记录回复 table:
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
这应该删除一条记录,但实际上所有记录都被删除了。
其实这个SQL有错误,内SQLselect min(id) from reply group by ex_type and ex_id having count(1) > 1
return只有字段的结果:'min(id)',外sql select id from () tmp
选择了一个不存在的字段 id 导致错误,但 MySQL 仍然执行此 sql 并删除所有记录。
我想知道为什么会这样。
有趣 - 这似乎是一个错误,因为在这种情况下 DELETE 应该会失败!!
无论如何,只要给 min(id) 附加一个别名(并删除 GROUP BY 之前那个奇怪的 'and'),一切都会好起来的......(虽然,我不会写这个查询这样)
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
您的查询在逻辑上是错误的。
这部分:
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
。
最重要的是,它不会 return 列 named/aliased 作为 id
.
这样:
select id from...
其实指的是table的id
和return的全部的id
的table 结果是所有行都被删除了。
您可以看到此行为 here.
我相信这就是你想要做的:
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
selects a non exsit field id
which lead to an error, but mysql execute this sql and delete all
records.
I want to konw why this happened.
这个子查询不会运行自己:
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' */
但是当它在子查询中 运行 时,根据范围解析规则 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
)
我正在使用 MySQL 版本 5.7.24。我想删除具有相同 ex_id 和 ex_type 的记录回复 table:
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
这应该删除一条记录,但实际上所有记录都被删除了。
其实这个SQL有错误,内SQLselect min(id) from reply group by ex_type and ex_id having count(1) > 1
return只有字段的结果:'min(id)',外sql select id from () tmp
选择了一个不存在的字段 id 导致错误,但 MySQL 仍然执行此 sql 并删除所有记录。
我想知道为什么会这样。
有趣 - 这似乎是一个错误,因为在这种情况下 DELETE 应该会失败!!
无论如何,只要给 min(id) 附加一个别名(并删除 GROUP BY 之前那个奇怪的 'and'),一切都会好起来的......(虽然,我不会写这个查询这样)
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
您的查询在逻辑上是错误的。
这部分:
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
。
最重要的是,它不会 return 列 named/aliased 作为 id
.
这样:
select id from...
其实指的是table的id
和return的全部的id
的table 结果是所有行都被删除了。
您可以看到此行为 here.
我相信这就是你想要做的:
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
selects a non exsit field id which lead to an error, but mysql execute this sql and delete all records.I want to konw why this happened.
这个子查询不会运行自己:
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' */
但是当它在子查询中 运行 时,根据范围解析规则 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
)