在MySQL中使用CTE进行更新或删除

Gio*_*sos 5 mysql common-table-expression sql-update sql-delete mysql-8.0

MySQL的新版本8.0现在支持Common Table Expressions

根据手册:

SELECT,UPDATE和DELETE语句的开头允许使用WITH子句:

WITH ... SELECT ...
WITH ... UPDATE ...
WITH ... DELETE ...
Run Code Online (Sandbox Code Playgroud)

因此,我认为,鉴于下表:

ID lastName firstName
----------------------
1  Smith    Pat
2  Smith    Pat
3  Smith    Bob
Run Code Online (Sandbox Code Playgroud)

我可以使用以下查询:

;WITH ToDelete AS 
(
   SELECT ID,
          ROW_NUMBER() OVER (PARTITION BY lastName, firstName ORDER BY ID) AS rn
   FROM mytable
)   
DELETE FROM ToDelete
Run Code Online (Sandbox Code Playgroud)

为了从表中删除重复项,就像在SQL Server中一样

原来我错了。当我尝试DELETE从MySQL Workbench 执行stament时出现错误:

错误代码:1146。表“ todelete”不存在

当我尝试UPDATE使用CTE 时,还会收到一条错误消息。

因此,我的问题是,如何在MySQL WITHUPDATEor DELETE语句的上下文中使用子句(如8.0版的手册中所述)?

Tim*_*sen 5

这似乎是 MySQL 中已发布的错误8.x。从这个错误报告

2015版SQL标准中,不能在UPDATE中定义CTE;MySQL 允许它但使 CTE 只读(我们现在正在更新文档以提及这一点)。这就是说,可以使用视图而不是 CTE;那么视图可能是可更新的,但由于窗口函数的存在,它被物化到一个临时表中(它没有合并)所以不可更新(我们也将在文档中提到它)。

以上所有内容也适用于 DELETE。

如果您遵循上述错误链接,您将看到建议使用 CTE 的解决方法,但它涉及以一对一映射将 CTE 连接到原始目标表。根据您的示例,即全面删除,尚不清楚您需要什么解决方法,是否继续使用 CTE 进行删除。


oys*_*ing 5

由于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; 
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解决方法,但它仍然需要一个`JOIN`。我使用 `CTE` 的目的(这是我在 SQL Server 中首选的 `DELETE` 方法,用于此类情况)是使 `DELETE` 语句尽可能简单。 (2认同)