2017-08-15 1186 views
0

我有一张表,需要使用Excel电子表格中的某些数据进行更新。我想沿着这些线路查询:在同一SQL查询中使用“WITH”和“UPDATE”语句

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) 

但甲骨文似乎不喜欢有一个“WITH”,并在同一查询“UPDATE”语句。我收到一个错误,说“缺少SELECT关键字”。我发现,我可以把SELECT语句中的临时表的定义,即

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

但是,这是可怕的,可怕的混乱的代码来定义像查询中间的那个右表。我只是在想这件事。必须有更好的方法来做到这一点。我应该建立一个全球临时表吗?或者我只是错过了一些简单的语法,这将使这个工作原来的方式?

+1

我认为创建临时表肯定是做到这一点的更好方法。 –

回答

0

您可以在更新中使用with子句;你只需要做到在正确的地方:

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子句:

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语句:

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; 

NB您必须加入到合并语句的源查询中的实际表格中,因为您试图更新要合并的列,而这在合并语句中无法完成 - 因此我已将合并连接切换到加入mytable.rowid。

您必须测试两个语句才能查看哪一个对数据最有效。

0

首先,我会建议使用JOIN进行更新这样的:

UPDATE 
(SELECT table1.value as OLD, table2.CODE as NEW 
FROM table1 
INNER JOIN table2 
ON table1.value = table2.DESC 
WHERE table1.UPDATETYPE='blah' 
) t 
SET t.OLD = t.NEW 

另外,如果你有正确的,创建表,并与一些ETL解决方案导入数据(Pentaho的,SSIS,Oracle商务智能套件)。从性能的角度来看,这是干净的。

或者使用游标 - 更多信息下面的链接: http://www.adp-gmbh.ch/ora/plsql/cursors/for_update.html

2

试试这个:

 
UPDATE mytable m 
    SET name = 
      (WITH temp 
       AS (SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM DUAL 
        UNION ALL /* Use UNION ALL instead of UNION in this case */ 
        SELECT 'efgh' AS oldvalue, 'klmn' AS newvalue FROM DUAL) 
      SELECT newvalue 
      FROM temp 
      WHERE temp.oldvalue = m.name) 

或者,您可以UST在Excel中插入相邻的单元此生成脚本:

="UPDATE YOUR_TABLE_NAME SET NAME="&CELL_WITH_NEW_VALUE&" WHERE NAME="&CELL_WITH_OLD_VALUE&"; COMMIT;" 

并将其拖到值列表的末尾。

之后,运行这个脚本,你就完成了!

+0

骨科医师的回答对我来说效果更好,但这也是一个非常好的解决方案。 +1 – schneiju