合并到一个select语句 - Oracle

时间:2012-06-01 09:18:36

标签: sql oracle select merge

是否可以使用select过滤某些要在表上合并的条目?

MERGE INTO (
  SELECT * FROM P4PCA2_PIVOT_CA
  WHERE ( CA_LIG_VTE_NUM_ID_PDT <> 0 )
)  ta
USING P4DAS2_DONARTSTK tb ON (tb.NUM_ID_PDT =ta.CA_LIG_VTE_NUM_ID_PDT)    
WHEN MATCHED THEN
  UPDATE SET ta.COD_SECVTE_REVENT=tb.COD_SECVTE_REVENT);

3 个答案:

答案 0 :(得分:5)

在Oracle中,您可以在(某些)视图或子查询上执行DML。指南是,如果Oracle能够从视图中检索物理行,则视图是可更新的。

因此,您可以在子查询上使用MERGE。在某些情况下这是有道理的。例如,假设您有一个包含状态列的表。您希望将新信息合并到此表中,但只修改具有STATUS='active'的行。你可以写:

MERGE INTO (SELECT * FROM mytable WHERE status='active') old
     USING (SELECT * FROM newtable) new
        ON (new.id = old.id)
      WHEN MATCHED THEN UPDATE SET old.data1=new.data1;

修改

这似乎在9iR2中产生ORA-00903。它的工作原理是11g。测试脚本:

create table t (id number, c varchar2(10));
insert into t (select rownum, 'aaa' from dual connect by level <= 1000);
merge into (select * from t where id <= 10) t 
     using (select 1 id from dual) d 
        ON (t.id = d.id) 
      when matched then update set c = 'iii';

答案 1 :(得分:0)

类似的东西:

MERGE INTO P4PCA2_PIVOT_CA ta
USING (
  select tb.*
  from P4DAS2_DONARTSTK tb
    join P4PCA2_PIVOT_CA ta on tb.NUM_ID_PDT = ta.CA_LIG_VTE_NUM_ID_PDT
  where ta.CA_LIG_VTE_NUM_ID_PDT <> 0 
) t ON (t.NUM_ID_PDT =ta.CA_LIG_VTE_NUM_ID_PDT)    
WHEN MATCHED THEN 
  update set ta.COD_SECVTE_REVENT=tb.COD_SECVTE_REVENT;

根据您的示例,我不确定USING部分的加入是否正确。

基本思想是仅在USING子句中选择要更新的行,而不是INTO子句的一部分。

答案 2 :(得分:0)

11g以下版本的解决方法:

创建一个包来保存变量值:

CREATE PACKAGE PKG_MY_VARIABLES 
as
  CA_LIG_VTE_NUM_ID_PDT number;
end;
/

创建引用该包的视图。

create or replace view V_P4PCA2_PIVOT_CA
as 
select * 
  from P4PCA2_PIVOT_CA 
 where CA_LIG_VTE_NUM_ID_PDT <> PKG_MY_VARIABLES.CA_LIG_VTE_NUM_ID_PDT ;

在运行merge语句之前,将package变量设置为您想要的值。

exec pkg_my_variables.CA_LIG_VTE_NUM_ID_PDT := 0;

对视图运行合并。

MERGE INTO V_P4PCA2_PIVOT_CA ta
USING P4DAS2_DONARTSTK tb ON (tb.NUM_ID_PDT =ta.CA_LIG_VTE_NUM_ID_PDT)    
WHEN MATCHED THEN
  UPDATE SET ta.COD_SECVTE_REVENT=tb.COD_SECVTE_REVENT);