【问题标题】:How do I run an update query in MySQL on a CTE?如何在 CTE 上的 MySQL 中运行更新查询?
【发布时间】:2020-06-16 17:20:55
【问题描述】:

我正在尝试创建一个 CTE,我认为它运行良好。但是,我想在此 CTE 上运行更新查询,但我在 MySQL WorkBench 中不断收到以下错误,

"Error Code: 1288. The target table pptest of the UPDATE is not updatable"

我环顾四周,但没有不了解任何变通方法,最重要的是,我对我的 MySQL 也不太了解。我的目标基本上是创建一个表/视图,其中包含一堆已分区的记录,并且每行都有一个索引号,由“row_num”表示。这是将表中的重复数据分组在一起,然后我希望在 row_num 大于 1 的结构上简单地运行更新查询。如此简单的逻辑,但我想不出任何其他方法来实现我的目标。请问有人可以帮忙吗?

我之前运行的完整查询是,

WITH cte as (select *, row_number() over (partition by col_a order by col_a) row_num from db_name.table_name) 
update cte set col_b='test' where row_num > 1

【问题讨论】:

    标签: mysql sql sql-update common-table-expression window-functions


    【解决方案1】:

    MySQL 不支持此语法。实际上,这看起来像 SQL Server 语法...您不能只是将查询从一个数据库移植到另一个数据库并期望它们正常工作。

    在 MySQL 中,您可以使用 update ... join 语法。但是,您需要一个唯一标识每一行的主键列(或一组列)作为连接条件。假设该列 id 是您的主键,那就是:

    update db_name.table_name t
    inner join (
        select id
        row_number() over (partition by col_a order by col_a) row_num 
        from db_name.table_name) 
    ) t1 on t1.id = t.id
    set t.col_b = 'test' 
    where t1.row_num > 1
    

    旁注:

    • 据我了解,您的查询旨在标记 col_a 上的重复项。但是您使用row_number() 的方式,不确定哪些重复行将被标记,因为您的order by 子句不是确定性的;你最好有一个over() 子句,例如:over (partition by col_a order by id)

    • row_number() 等窗口函数仅在 MySQL 8.0 中可用

    【讨论】:

      【解决方案2】:

      更新和删除在 mysql 临时表中不起作用。一种解决方法是将原始表与临时表 CTE 连接并更新原始表:

          WITH cte as (select *, row_number() 
      over (partition by col_a order by col_a) row_num 
      from db_name.table_name) 
          
          update db_name.table_name T1 
      Join 
      cte on T1.col_a = cte.col_a set t1.col_b='test' where cte.row_num > 1
      

      这也适用于删除指令。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-05
        • 2014-11-16
        • 2014-04-10
        • 1970-01-01
        • 1970-01-01
        • 2019-09-27
        • 2014-06-05
        • 1970-01-01
        相关资源
        最近更新 更多