Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a CTE to UPDATE or DELETE in MySQL

The new version of MySQL, 8.0, now supports Common Table Expressions.

According to the manual:

A WITH clause is permitted at the beginning of SELECT, UPDATE, and DELETE statements:

WITH ... SELECT ...
WITH ... UPDATE ...
WITH ... DELETE ...

So, I thought, given the following table:

ID lastName firstName
----------------------
1  Smith    Pat
2  Smith    Pat
3  Smith    Bob

I can use the following query:

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

in order to delete duplicates from the table, just like I could do in SQL Server.

It turns out I was wrong. When I try to execute the DELETE stament from MySQL Workbench I get the error:

Error Code: 1146. Table 'todelete' doesn't exist

I also get an error message when I try to do an UPDATE using the CTE.

So, my question is, how could one use a WITH clause in the context of an UPDATE or DELETE statement in MySQL (as cited in the manual of version 8.0)?

like image 411
Giorgos Betsos Avatar asked Jun 11 '18 13:06

Giorgos Betsos


1 Answers

This appears to be a published bug in MySQL 8.x. From this bug report:

In the 2015 version of the SQL standard, a CTE cannot be defined in UPDATE; MySQL allows it but makes the CTE read-only (we're updating the documentation now to mention this). This said, one could use a view instead of the CTE; then the view may be updatable, but due to the presence of window functions it is materialized into a temporary table (it is not merged) so is not updatable (we're going to mention it in the doc as well).

All the above applies to DELETE too.

If you follow the above bug link, you will see a workaround suggested for using a CTE, but it involved joining the CTE to the original target table in a one-to-one mapping. Based on your example, which is a blanket delete, it is not clear what workaround you need, were to proceed using a CTE for your delete.

like image 180
Tim Biegeleisen Avatar answered Sep 21 '22 07:09

Tim Biegeleisen