新版本的MySQL 8.0现在支持Common Table Expressions。
根据手册:
在SELECT,UPDATE和DELETE语句的开头允许使用WITH子句:
WITH ... SELECT ...
WITH ... UPDATE ...
WITH ... DELETE ...
所以,我想,如下表所示:
ID lastName firstName
----------------------
1 Smith Pat
2 Smith Pat
3 Smith Bob
我可以使用以下查询:
;WITH ToDelete AS
(
SELECT ID,
ROW_NUMBER() OVER (PARTITION BY lastName, firstName ORDER BY ID) AS rn
FROM mytable
)
DELETE FROM ToDelete
为了删除表格中的重复项,就像我在SQL Server中所做的那样。
事实证明我错了。当我尝试从MySQL Workbench执行DELETE
时,我得到错误:
错误代码:1146。表'todelete'不存在
当我尝试使用CTE UPDATE
时,我也收到错误消息。
所以,我的问题是,如何在MySQL中WITH
或UPDATE
语句的上下文中使用DELETE
子句(如8.0版手册中所述)?
答案 0 :(得分:3)
这似乎是MySQL 8.x
中已发布的错误。从bug report:
在2015版SQL标准中,无法在UPDATE中定义CTE; MySQL允许它,但使CTE只读(我们现在更新文档提到这一点)。 这就是说,人们可以使用视图而不是CTE;然后视图可以更新,但是由于窗口函数的存在,它被实现为临时表(它没有被合并),因此不可更新(我们也将在doc中提及它)。
以上所有内容也适用于DELETE。
如果您按照上述错误链接,您将看到建议使用CTE的解决方法,但它涉及以一对一的映射方式将CTE加入原始目标表。根据您的示例(即全面删除),您不清楚需要使用CTE进行删除。
答案 1 :(得分:1)
由于CTE不可更新,因此您需要引用原始表来删除行。我想你正在寻找这样的东西:
WITH ToDelete AS
(
SELECT ID,
ROW_NUMBER() OVER (PARTITION BY lastName, firstName ORDER BY ID) AS rn
FROM mytable
)
DELETE FROM mytable USING mytable JOIN ToDelete ON mytable.ID = ToDelete.ID
WHERE ToDelete.rn > 1;