在Oracle上使用内部联接更新语句

use*_*743 280 sql oracle inner-join ora-00933

我有一个在MySQL中工作正常的查询,但是当我在Oracle上运行时,我收到以下错误:

SQL错误:ORA-00933:SQL命令未正确结束
00933. 00000 - "SQL命令未正确结束"

查询是:

UPDATE table1
INNER JOIN table2 ON table1.value = table2.DESC
SET table1.value = table2.CODE
WHERE table1.UPDATETYPE='blah';
Run Code Online (Sandbox Code Playgroud)

Ton*_*ews 385

该语法在Oracle中无效.你可以这样做:

UPDATE table1 SET table1.value = (SELECT table2.CODE
                                  FROM table2 
                                  WHERE table1.value = table2.DESC)
WHERE table1.UPDATETYPE='blah'
AND EXISTS (SELECT table2.CODE
            FROM table2 
            WHERE table1.value = table2.DESC);
Run Code Online (Sandbox Code Playgroud)

或者您可以这样做:

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
Run Code Online (Sandbox Code Playgroud)

(这取决于内联视图是否被Oracle认为是可更新的).

  • 第二个示例的好处是允许您在实际执行更新之前测试SQL. (38认同)
  • 第二个例子对我有用.我喜欢那个因为它看起来干净可读.在性能方面,不知道两者之间的利弊是什么.但是,我现在并不担心这个问题,因为我使用它来制作一个可以纠正错误数据的脚本. (10认同)
  • 有关可更新连接的密钥保留要求的说明:https://asktom.oracle.com/pls/asktom/f?p = 100:11:::::: P11_QUESTION_ID:548422757486 (10认同)
  • 我做了第二个例子但是必须在select中的列名中添加别名,然后在SET中通过它们的名称引用它们但是它有效,谢谢 (5认同)
  • 第二个为我工作:).Oracle是一个强大但奇怪的动物:/ (5认同)
  • 得到这个 - "ORA-01779:无法修改映射到非密钥保留表的列",然后http://stackoverflow.com/questions/9335536/oracle-update-join-non-key-preserved-table帮助. (2认同)

Qua*_*noi 196

用这个:

MERGE
INTO    table1 trg
USING   (
        SELECT  t1.rowid AS rid, t2.code
        FROM    table1 t1
        JOIN    table2 t2
        ON      table1.value = table2.DESC
        WHERE   table1.UPDATETYPE='blah'
        ) src
ON      (trg.rowid = src.rid)
WHEN MATCHED THEN UPDATE
    SET trg.value = code;
Run Code Online (Sandbox Code Playgroud)

  • 完美的工作,但Oracle要求我说'合并到表1 t'等等. (2认同)

Rol*_*and 22

合并where子句为我工作:

MERGE into table1
USING table2
ON (table1.id = table2.id)
WHEN MATCHED THEN UPDATE SET table1.startdate = table2.start_date
WHERE table1.startdate > table2.start_date;
Run Code Online (Sandbox Code Playgroud)

您需要该MERGE子句,因为WHERE无法更新子句中引用的列.


Mor*_*son 13

 UPDATE ( SELECT t1.value, t2.CODE
          FROM table1 t1
          INNER JOIN table2 t2 ON t1.Value = t2.DESC
          WHERE t1.UPDATETYPE='blah')
 SET t1.Value= t2.CODE
Run Code Online (Sandbox Code Playgroud)


duv*_*uvo 11

不要使用上面的一些答案.

有人建议使用嵌套的SELECT,不要这样做,这是极其缓慢的.如果要更新许多记录,请使用join,如下所示:

update (select bonus 
        from employee_bonus b 
        inner join employees e on b.employee_id = e.employee_id 
        where e.bonus_eligible = 'N') t
set t.bonus = 0;
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此链接. http://geekswithblogs.net/WillSmith/archive/2008/06/18/oracle-update-with-join-again.aspx.

此外,请确保您要加入的所有表都有主键.

  • SQL 错误:ORA-01779:无法修改映射到非键保留表的列 (2认同)

Ale*_*noy 7

如图所示这里,第一个解决方案由托尼·安德鲁斯提出的一般语法是:

update some_table s
set   (s.col1, s.col2) = (select x.col1, x.col2
                          from   other_table x
                          where  x.key_value = s.key_value
                         )
where exists             (select 1
                          from   other_table x
                          where  x.key_value = s.key_value
                         )
Run Code Online (Sandbox Code Playgroud)

我认为这很有趣,特别是如果你想要更新多个字段.


小智 5

甲骨文运行良好

merge into table1 t1
using (select * from table2) t2
on (t1.empid = t2.empid)
when matched then update set t1.salary = t2.salary
Run Code Online (Sandbox Code Playgroud)