2017-08-15 272 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