我有一个在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';


评论

当我尝试在Oracle中设置table2来测试答案时,我发现Oracle拒绝了DESC作为列名。

抱歉,我只是将原始列名缩写为desc,显然不是db

#1 楼

该语法在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);


或者您可以执行以下操作:

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


这取决于如果内联视图被Oracle认为是可更新的
(要更新第二条语句取决于
此处列出的某些规则)。

评论


我做了第二个例子,但是必须在选择的列名称中添加别名,然后在SET中通过它们的名称引用它们,但是有效,谢谢

–古斯塔沃·卢比奥(Gustavo Rubio)
2011年6月6日在2:25

第二个示例的好处是允许您在实际执行更新之前测试SQL。

–丹尼尔·赖斯(Daniel Reis)
2012年1月19日上午10:18

第二个例子对我有用。我喜欢它,因为它看起来干净而且可读。不知道两者之间在性能方面的优缺点。但是,我现在并不担心,因为我将其用于一次性脚本来纠正不良数据。

–nemo
2012年5月2日,0:03



第二为我工作:)。甲骨文是一个强大但怪异的动物:/

–elrado
2014-2-18在5:22

有关可更新连接的键保留要求的说明:asktom.oracle.com/pls/asktom/…

–Vadzim
15年2月12日在12:17

#2 楼

使用此:

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;


评论


工作正常,但是Oracle要求我说合并到表1 t中,依此类推。

– Michael-O
13年5月6日在12:12

参加聚会晚了,但这仍然是一个很好的话题。我需要知道,'...我错过了什么吗?主表“ table1”。在使用中,table1的别名为t1。 Table2,别名为t2,但在ON中,引用为...?外部表1-不是t1-这是对外部表的引用还是类型?表2?不是t2? Je suis感到困惑。更好别名的粉丝...

– Marc
2014年7月21日19:02

这里只是一点,如果您的密钥(trg.rowid或src.rid)具有一个重复的项目,则此子句将引发错误:ora-30926.ora-code.com

–亨利克
16年4月25日在12:25

@Marc在ON中,trg是主表table1(逻辑上为“外部”表)的别名,而src引用USING组(逻辑上为“内部表”)。但是,是的,也许本来可以更好地引用它,但是我能够遵循它。

–vapcguy
16年7月22日在20:32

@supernova:Tony的答案是更新内联视图。在某些情况下这可以工作,但是视图必须“保留键”(每个联接表必须在其主键或唯一字段集上相等联接)。这样可以确保目标表中的每条记录最多对结果行集中的一条记录有所贡献,因此,目标表中的每条记录最多更新一次。

– Quassnoi
18年1月15日在13:03



#3 楼

带有MERGE子句的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;


您需要WHERE子句,因为无法更新ON子句中引用的列。

评论


这个版本可以说更干净,但是它不是触发友好的,因为我知道没有办法避免使用此语法为未更改的行触发更新触发器。 (我假设更改的行需要触发器。)

–sf_jeff
19-09-29在15:46

#4 楼

 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


#5 楼

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

有人建议使用嵌套的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;


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

此外,请确保要连接的所有表上都有主键。

#6 楼

如此处所示,Tony Andrews提出的第一个解决方案的一般语法是:

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
                         )


我认为这很有趣,特别是如果您要更新多个字段。 br />

评论


这对我不起作用。它更新整个表。

– Natassia Tavares
17年11月22日在12:14

#7 楼

oracle可以正常工作

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


评论


可以通过在其末尾添加逗号来设置多个属性。我需要在与“ UserName”列上的表(t1.UserName = t2.UserName)匹配后,在表上执行t1.First_Name = t2.FirstName,t1.Last_Name = t2.LastName,以从名为UserInfo的表中检索其名称(从用户信息中选择*)t2)。数据库是如此,它在任何地方都使用UserName作为UserInfo的主键,而不是直接在表中放置FirstName和LastName。这样就解决了!

–vapcguy
2016年7月20日在21:56



这个答案对Quassnoi在您提出的五年之前已经提供的答案没有任何帮助。

–饲料
17年11月14日在14:18

#8 楼

以下语法对我有用。

UPDATE
(SELECT A.utl_id,
    b.utl1_id
    FROM trb_pi_joint A
    JOIN trb_tpr B
    ON A.tp_id=B.tp_id Where A.pij_type=2 and a.utl_id is null
)
SET utl_id=utl1_id;


评论


@JimGarrison请重新编辑此答案,以便删除我的下注...。我试图使用此语法,但未更新我的表。我发现了为什么-我的SET做一个REPLACE,而我试图清空该列中的特定字符串-原来Oracle将''视为空,并且该字段不能为空。我以为语法只是更新一个临时表,而不是真正的临时表,但是我错了。

–vapcguy
16年7月22日在21:03



#9 楼

对于表2,使用描述代替desc,

update
  table1
set
  value = (select code from table2 where description = table1.value)
where
  exists (select 1 from table2 where description = table1.value)
  and
  table1.updatetype = 'blah'
;


评论


为什么要在table2上触发两个单独的查询

– Jitendra Vispute
2015年9月14日上午8:19

#10 楼

出于完整性的考虑,并且由于我们在谈论Oracle,因此也可以这样做:

declare
begin
  for sel in (
    select table2.code, table2.desc
    from table1
    join table2 on table1.value = table2.desc
    where table1.updatetype = 'blah'
  ) loop
    update table1 
    set table1.value = sel.code
    where table1.updatetype = 'blah' and table1.value = sel.desc;    
  end loop;
end;
/


评论


这可以做到,但这是最慢的方法。

– APC
19年3月19日在12:37

#11 楼

UPDATE table1 t1
SET t1.value = 
    (select t2.CODE from table2 t2 
     where t1.value = t2.DESC) 
WHERE t1.UPDATETYPE='blah';


#12 楼

UPDATE IP_ADMISSION_REQUEST ip1
SET IP1.WRIST_BAND_PRINT_STATUS=0
WHERE IP1.IP_ADM_REQ_ID        =
  (SELECT IP.IP_ADM_REQ_ID
  FROM IP_ADMISSION_REQUEST ip
  INNER JOIN VISIT v
  ON ip.ip_visit_id=v.visit_id
  AND v.pat_id     =3702
  ); `enter code here`


#13 楼

UPDATE (SELECT T.FIELD A, S.FIELD B
FROM TABLE_T T INNER JOIN TABLE_S S
ON T.ID = S.ID)
SET B = A;


A和B是别名字段,您无需指向表。

评论


嗨,丹。您正在发布一个已经很不错的答案的老问题。您能解释什么时候您的问题比其他解决方案更可取吗?

–诺埃尔·威德默(Noel Widmer)
17年5月30日在9:52

当然,我已经看到了一个答案,其中b = a是通过指向表名(table1.B = table2.A)而写的,但是没有必要指向该表。

–丹·安德森(Dan Anderson)
17年5月30日在11:31

您实际上是在更新视图中的字段,这些字段已映射到表。如果内部视图使用别名h,则“自我记录”版本将为“ set h.b = h.a”。

–sf_jeff
19-09-29在15:49

#14 楼

Oracle基础在此方面运行良好。
https://oracle-base.com/articles/misc/updates-based-on-queries
从此链接-我对上面的内容进行了修改对我不起作用的查询(来自使用行ID的mathguy的答案)
MERGE /*+ APPEND PARALLEL(8) */ INTO dest_table tt
USING source_table st
ON (tt.identifier = st.identifier)
WHEN MATCHED THEN
  UPDATE SET tt.number = st.number;

这里我有两个表:source和dest。它们都有一个共同的varchar字段,我正在将源标识字段(PK)添加到dest表中。

#15 楼

update table1  a 
   set a.col1='Y' 
 where exists(select 1 
                from table2 b
               where a.col1=b.col1 
                 and a.col2=b.col2
             )