You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL中使用ROW_NUMBER()函数执行DELETE时报1288错误:目标表不可更新问题咨询

解决MySQL中使用CTE+ROW_NUMBER()删除重复数据时的1288错误

我之前也碰到过这个MySQL的坑!咱们来一步步拆解问题和解决办法:

问题原因分析

你遇到的Error Code: 1288本质原因是:MySQL不允许直接对CTE(公共表表达式)执行DELETE/UPDATE操作,哪怕你的CTE和基表同名。

当你写WITH idpublisher AS (...) DELETE FROM idpublisher时,MySQL会把这个idpublisher识别为CTE生成的临时结果集(相当于一个不可更新的视图),而不是你实际的物理表。即使CTE包含了主键,它依然是一个虚拟的数据集,不支持直接修改操作,所以会抛出“目标表不可更新”的错误。

解决方案

这里提供两种可靠的解决方法,都能实现你删除重复publisher数据的需求:

方法一:通过JOIN关联CTE删除基表数据

这种方法的核心是直接对物理表执行DELETE,用CTE作为筛选条件的来源,而不是去删除CTE本身:

WITH idpublisher_cte AS (
    SELECT 
        id, -- 这里必须选你的表的主键/唯一标识字段
        ROW_NUMBER() OVER(PARTITION BY publisher ORDER BY id) AS RowNumber -- 建议用主键排序,保证保留固定行
    FROM idpublisher
)
DELETE ip
FROM idpublisher ip
JOIN idpublisher_cte cte ON ip.id = cte.id
WHERE cte.RowNumber > 1;

注意:把ORDER BY id换成你需要保留的行的排序规则(比如created_at DESC保留最新行),如果只按publisher排序,行号的顺序是不确定的,可能导致每次删除的行不一致。

方法二:使用嵌套子查询(无CTE)

如果你的MySQL版本不支持CTE(比如5.7及以前),可以用两层嵌套子查询来绕开“不能直接引用正在修改的表”的限制:

DELETE FROM idpublisher
WHERE id IN (
    SELECT id FROM (
        SELECT 
            id,
            ROW_NUMBER() OVER(PARTITION BY publisher ORDER BY id) AS RowNumber
        FROM idpublisher
    ) AS temp_table -- 必须给内层子查询加别名
    WHERE RowNumber > 1
);

这里的内层子查询会生成一个临时结果集,外层查询通过这个临时集找到要删除的主键,再对原表执行删除操作,完美避开MySQL的限制。

内容的提问来源于stack exchange,提问作者Muhammad Saleh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 01:37:45