首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 关于SQL脚本升级的一个问题(急) [已结帖,结帖人:simeng1128]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • simeng1128
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-08-19 22:01:43 楼主
        我现在要写一个升级脚本去升级数据库里面的一些表,这个表里面已经存在一些记录。现在要做的工作是:表里面已经存在的记录就直接去更新某些字段,如果不存在就插进去新的记录。例如:下面的语句,如果存在的就更新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语句里面有没有这种条件语句,而且可以进行批处理的来简化操作。
    60  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hebo2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

      3

    发表于:2008-08-19 22:07:221楼 得分:40
    用merge

    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

    ===============================================================

    ref: http://tomszrp.itpub.net/post/11835/263865

    在Oracle 10g之前,merge语句支持匹配更新和不匹配插入2种简单的用法,在10g中Oracle对merge语句做了增强,增加了条件选项和DELETE操作。下面我通过一个demo来简单介绍一下10g中merge的增强和10g前merge的用法。

     

    参考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;

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • simeng1128
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-20 08:42:552楼 得分:0
      嗯!谢谢一楼的,说得很详细。我想起来了,不过Merge是用一个表去更新另一个表吧?我现在只有一个表,再就是一个.sql文件,里面有一些插入语句,它是把目标表的记录删掉,然后就是几十个插入语句再插进去。我的工作就是改动它,目表表里有的记录,不需要重新插入,而是把每条记录的某些字段改一下;没有的再执行插入语句。那个merge语句更新的时候怎么对多条记录的某个字段更新啊?比如000001到000046的四十多条记录的vc_dynamic_SQL字段都要修改的。我对SQL语句不是很熟练,只会一些简单的。你能不能再跟我解释一下上面的疑问。谢谢了。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bobfang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-08-20 09:55:293楼 得分:20
    建一个中间表,把原因的insert语句改为insert到中间表,最后再执行一次merge中间表到原目的表。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bobfang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-08-20 09:58:474楼 得分:0
    如果在原目的表中,vc_trade_level或vc_trade_level加c_trade_type是唯一的,那么上面我说的方法是没问题的,否则还需推敲推敲。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • simeng1128
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-25 11:59:255楼 得分:0
    谢谢各位!收贴散分了。
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved