我现在要写一个升级脚本去升级数据库里面的一些表,这个表里面已经存在一些记录。现在要做的工作是:表里面已经存在的记录就直接去更新某些字段,如果不存在就插进去新的记录。例如:下面的语句,如果存在的就更新vc_dynamic_SQL字段,如果不存在此记录,就将它插入现在的表。 --判断vc_trade_type=000009 declare iCountNum number; begin iCountNum := 0; select count(*) into iCountNum from TTradeTypes where vc_trade_level='000009' and c_trade_type='0'; if (iCountNum > 0) then update TTradeTypes set vc_dynamic_SQL= 'select a.vc_inter_code from tstockinfo a where a.c_asset_class=''4'' and a.c_mixed_type=''2'' ' else insert into TTradeTypes (l_date,l_serial_id,c_trade_type,vc_trade_level,l_parent_id,l_fund_id,vc_trade_no,vc_trade_name,l_root_id,c_stockpoo l_type,vc_dynamic_SQL) values(sf_init_date,SeqTradeTypeNo.NextVal,'0','000009',-1,-1,SeqTradeTypeNo.NextVal,'货币基金', SeqTradeTypeNo.NextVal,'', 'select a.vc_inter_code from tstockinfo a where a.c_asset_class=''4'' and a.c_mixed_type=''2'''); end if; end; 当然还有vc_trade_type从000001到000059等几十条记录需要判断,表里面存在的就40多条,这些记录的类型c_trade_type都为0。这样逐个去判断比较麻烦,效率也不高,要比较几十次。请问各位SQL语句里面有没有这种条件语句,而且可以进行批处理的来简化操作。
MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句。通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,连接条件匹配上的进行UPDATE,无法匹配的执行INSERT。这个语法仅需要一次全表扫描就完成了全部工作,执行效率要高于INSERT+UPDATE。 下面看个具体的例子: SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A; 表已创建。 SQL> CREATE TABLE T1 AS 2 SELECT ROWNUM ID, OWNER, TABLE_NAME, CAST('TABLE' AS VARCHAR2(100)) OBJECT_TYPE 3 FROM DBA_TABLES; 表已创建。 SQL> MERGE INTO T1 USING T 2 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME AND T.OBJECT_TYPE = T1.OBJECT_TYPE) 3 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID 4 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME, T.OBJECT_TYPE); 6165 行已合并。 SQL> SELECT ID, OWNER, OBJECT_NAME, OBJECT_TYPE FROM T 2 MINUS 3 SELECT * FROM T1; 未选定行 MERGE语法其实很简单,下面稍微修改一下例子。 SQL> DROP TABLE T; 表已丢弃。 SQL> DROP TABLE T1; 表已丢弃。 SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A; 表已创建。 SQL> CREATE TABLE T1 AS SELECT ROWNUM ID, OWNER, TABLE_NAME FROM DBA_TABLES; 表已创建。 SQL> MERGE INTO T1 USING T 2 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME) 3 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID 4 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME); MERGE INTO T1 USING T * ERROR 位于第 1 行: ORA-30926: 无法在源表中获得一组稳定的行 这个错误是使用MERGE最常见的错误,造成这个错误的原因是由于通过连接条件得到的T的记录不唯一。最简单的解决方法类似: SQL> MERGE INTO T1 2 USING (SELECT OWNER, OBJECT_NAME, MAX(ID) ID FROM T GROUP BY OWNER, OBJECT_NAME) T 3 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME) 4 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID 5 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME); 5775 行已合并。 另外,MERGE语句的UPDATE不能修改用于连接的列,否则会报错,详细信息可以参考:http://blog.itpub.net/post/468/14844
参考Oracle 的SQL Reference,大家可以看到Merge Statement的语法如下: MERGE [hint] INTO [schema .] table [t_alias] USING [schema .] { table | view | subquery } [t_alias] ON ( condition ) WHEN MATCHED THEN merge_update_clause WHEN NOT MATCHED THEN merge_insert_clause;