使用"WITH";和“更新"同一SQL查询中的语句 [英] Using "WITH" and "UPDATE" statements in the same SQL query

查看:91
本文介绍了使用"WITH";和“更新"同一SQL查询中的语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个表,需要使用Excel电子表格中的一些数据进行更新.我正在考虑按照以下方式进行查询:

I have a table that I need to update with some data from an Excel spreadsheet. I am thinking of a query along these lines:

WITH temp AS(
(SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
(SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
)
UPDATE mytable
   SET name = (SELECT newvalue FROM temp WHERE mytable.name = temp.oldvalue)

但是Oracle似乎不喜欢在同一查询中包含"WITH"和"UPDATE"语句.我收到一条错误消息:缺少SELECT关键字".我发现我可以将temp表定义放在SELECT语句中,即

But Oracle doesn't seem to like having a "WITH" and "UPDATE" statement in the same query. I get an error saying "missing SELECT keyword". I have found out that I can put the temp table definition within the SELECT statement, i.e.

 SET name = (SELECT newvalue FROM (
         (SELECT 'abcd' AS oldvalue, 'defg' AS  newvalue FROM dual) UNION
         (SELECT .....)
          ) temp WHERE mytable.name = temp.oldvalue)

但这是可怕的,非常混乱的代码,用于在查询中间定义类似的表.我只是想想就退缩了.必须有一个更好的方法来做到这一点.我应该建立一个全局临时表吗?还是我只是缺少一些简单的语法来使这项工作按原始方式进行?

But that is horribly, horribly messy code to define a table like that right in the middle of the query. I cringe just thinking about it. There has to be a better way to do this. Should I set up a global temporary table? Or am I just missing some simple syntax that would make this work the original way?

推荐答案

您可以在更新中使用with子句;您只需要在正确的位置进行操作即可:

You can use a with clause in an update; you just have to do it in the right place:

UPDATE mytable
   SET name = (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
                            (SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
                           )
               SELECT newvalue
               FROM   temp
               WHERE  mytable.name = temp.oldvalue);

但是,您可能只想更新temp子查询中存在的行,因此您将需要一个附加的where子句:

However, you're probably wanting to only update rows that exist in the temp subquery, so you would need an additional where clause:

UPDATE mytable
   SET name = (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
                            (SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
                           )
               SELECT newvalue
               FROM   temp
               WHERE  mytable.name = temp.oldvalue)
WHERE  EXISTS (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
                            (SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
                           )
               SELECT NULL
               FROM   temp
               WHERE  mytable.name = temp.oldvalue);

或者,使用MERGE语句:

Alternatively, use a MERGE statement:

merge into mytable tgt
  using (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
                      (SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
                     )
         SELECT mytable.rowid r_id,
                temp.newvalue
         FROM   temp
         inner  join mytable on mytable.name = temp.oldvalue) src
    on (tgt.rowid = src.r_id)
when matched then
update set tgt.name = src.newvalue;

您必须在merge语句的源查询中连接到实际表,因为您正试图更新正在连接的列,而这在merge语句中是无法做到的-因此,我将合并连接切换为加入mytable.rowid.

N.B. you have to join to the actual table in the source query of the merge statement because you're trying to update the column that's being joined on, which you can't do in a merge statement - hence I've switched the merge join to join on mytable.rowid.

您必须测试两个语句,以查看哪个语句在您的数据上性能最高.

You'd have to test both statements to see which one is most performant on yor data.

这篇关于使用"WITH";和“更新"同一SQL查询中的语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆