11

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中所做的那样。

事实证明我错了。当我尝试DELETE从 MySQL Workbench 执行语句时,出现错误:

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

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

所以,我的问题是,如何在 MySQL 中的or语句WITH的上下文中使用子句(如 8.0 版手册中所述)?UPDATEDELETE

4

2 回答 2

8

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

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

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

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

于 2018-06-11T13:48:57.673 回答
7

由于 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; 
于 2018-06-12T11:32:07.410 回答