<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-314  評(píng)論-209  文章-0  trackbacks-0

    24/05/2005 14:37 FP 在數(shù)據(jù)倉(cāng)庫(kù)中的轉(zhuǎn)換和裝載過(guò)程中,經(jīng)常會(huì)使用MERGE語(yǔ)句,這里簡(jiǎn)單總結(jié)一下。


    MERGE語(yǔ)句是Oracle9i新增的語(yǔ)法,用來(lái)合并UPDATE和INSERT語(yǔ)句。通過(guò)MERGE語(yǔ)句,根據(jù)一張表或子查詢的連接條件對(duì)另外一張表進(jìn)行查詢,連接條件匹配上的進(jìn)行UPDATE,無(wú)法匹配的執(zhí)行INSERT。這個(gè)語(yǔ)法僅需要一次全表掃描就完成了全部工作,執(zhí)行效率要高于INSERT+UPDATE。
    下面看個(gè)具體的例子:
    SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A;
    表已創(chuàng)建。
    SQL> CREATE TABLE T1 AS
    2 SELECT ROWNUM ID, OWNER, TABLE_NAME, CAST('TABLE' AS VARCHAR2(100)) OBJECT_TYPE
    3 FROM DBA_TABLES;
    表已創(chuàng)建。
    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語(yǔ)法其實(shí)很簡(jiǎn)單,下面稍微修改一下例子。
    SQL> DROP TABLE T;
    表已丟棄。
    SQL> DROP TABLE T1;
    表已丟棄。
    SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A;
    表已創(chuàng)建。
    SQL> CREATE TABLE T1 AS SELECT ROWNUM ID, OWNER, TABLE_NAME FROM DBA_TABLES;
    表已創(chuàng)建。
    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: 無(wú)法在源表中獲得一組穩(wěn)定的行
    這個(gè)錯(cuò)誤是使用MERGE最常見的錯(cuò)誤,造成這個(gè)錯(cuò)誤的原因是由于通過(guò)連接條件得到的T的記錄不唯一。最簡(jiǎn)單的解決方法類似:
    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語(yǔ)句的UPDATE不能修改用于連接的列,否則會(huì)報(bào)錯(cuò),詳細(xì)信息可以參考:
    http://blog.itpub.net/post/468/14844

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

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

    在Oracle 10g之前,merge語(yǔ)句支持匹配更新和不匹配插入2種簡(jiǎn)單的用法,在10g中Oracle對(duì)merge語(yǔ)句做了增強(qiáng),增加了條件選項(xiàng)和DELETE操作。下面我通過(guò)一個(gè)demo來(lái)簡(jiǎn)單介紹一下10g中merge的增強(qiáng)和10g前merge的用法。

     

    參考Oracle 的SQL Reference,大家可以看到Merge Statement的語(yǔ)法如下:
    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;

    下面我在windows xp 下10.2.0.1版本上做一個(gè)測(cè)試看看

    SQL> select * from v$version;
    BANNER
    ----------------------------------------------------------------
    Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
    PL/SQL Release 10.2.0.1.0 - Production
    CORE    10.2.0.1.0      Production
    TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
    NLSRTL Version 10.2.0.1.0 - Production
    SQL>
    一、創(chuàng)建測(cè)試用的表
    SQL> create table subs(msid number(9),
    2                    ms_type char(1),
    3                    areacode number(3)
    4                    );
    表已創(chuàng)建。
    SQL> create table acct(msid number(9),
    2                    bill_month number(6),
    3                    areacode   number(3),
    4                    fee        number(8,2) default 0.00);
    表已創(chuàng)建。
    SQL>
    SQL> insert into subs values(905310001,0,531);
    已創(chuàng)建 1 行。
    SQL> insert into subs values(905320001,1,532);
    已創(chuàng)建 1 行。
    SQL> insert into subs values(905330001,2,533);
    已創(chuàng)建 1 行。
    SQL> commit;
    提交完成。
    SQL>
     
    二、下面先演示一下merge的基本功能
    1) matched 和not matched clauses 同時(shí)使用
    merge into acct a
    using subs b on (a.msid=b.msid)
    when MATCHED then
    update set a.areacode=b.areacode
    when NOT MATCHED then
    insert(msid,bill_month,areacode)
    values(b.msid,'200702',b.areacode);
    2) 只有not matched clause,也就是只插入不更新
    merge into acct a
    using subs b on (a.msid=b.msid)
    when NOT MATCHED then
    insert(msid,bill_month,areacode)
    values(b.msid,'200702',b.areacode);
    3) 只有matched clause, 也就是只更新不插入
    merge into acct a
    using subs b on (a.msid=b.msid)
    when MATCHED then
    update set a.areacode=b.areacode
    Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
    Connected as study
    SQL> select * from subs;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905310001 0            531
    905320001 1            532
    905330001 2            533
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    SQL>
    SQL> merge into acct a
    2       using subs b on (a.msid=b.msid)
    3     when MATCHED then
    4          update set a.areacode=b.areacode
    5     when NOT MATCHED then
    6          insert(msid,bill_month,areacode)
    7          values(b.msid,'200702',b.areacode);
    Done
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    905320001     200702      532       0.00
    905330001     200702      533       0.00
    905310001     200702      531       0.00
    SQL> insert into subs values(905340001,3,534);
    1 row inserted
    SQL> select * from subs;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905340001 3            534
    905310001 0            531
    905320001 1            532
    905330001 2            533
    SQL>
    SQL> merge into acct a
    2       using subs b on (a.msid=b.msid)
    3     when NOT MATCHED then
    4          insert(msid,bill_month,areacode)
    5          values(b.msid,'200702',b.areacode);
    Done
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    905320001     200702      532       0.00
    905330001     200702      533       0.00
    905310001     200702      531       0.00
    905340001     200702      534       0.00
    SQL> update subs set areacode=999;
    4 rows updated
    SQL> select * from subs;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905340001 3            999
    905310001 0            999
    905320001 1            999
    905330001 2            999
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    905320001     200702      532       0.00
    905330001     200702      533       0.00
    905310001     200702      531       0.00
    905340001     200702      534       0.00
    SQL>
    SQL> merge into acct a
    2       using subs b on (a.msid=b.msid)
    3     when MATCHED then
    4          update set a.areacode=b.areacode;
    Done
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    905320001     200702      999       0.00
    905330001     200702      999       0.00
    905310001     200702      999       0.00
    905340001     200702      999       0.00
    SQL>
     
    三、10g中增強(qiáng)一:條件操作
    1) matched 和not matched clauses 同時(shí)使用
    merge into acct a
    using subs b on (a.msid=b.msid)
    when MATCHED then
    update set a.areacode=b.areacode
    where b.ms_type=0
    when NOT MATCHED then
    insert(msid,bill_month,areacode)
    values(b.msid,'200702',b.areacode)
    where b.ms_type=0;
    2) 只有not matched clause,也就是只插入不更新
    merge into acct a
    using subs b on (a.msid=b.msid)
    when NOT MATCHED then
    insert(msid,bill_month,areacode)
    values(b.msid,'200702',b.areacode)
    where b.ms_type=0;
    3) 只有matched clause, 也就是只更新不插入
    merge into acct a
    using subs b on (a.msid=b.msid)
    when MATCHED then
    update set a.areacode=b.areacode
    where b.ms_type=0;
    Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
    Connected as study
    SQL> select * from subs;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905310001 0            531
    905320001 1            532
    905330001 2            533
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    SQL>
    SQL> merge into acct a
    2       using subs b on (a.msid=b.msid)
    3     when MATCHED then
    4          update set a.areacode=b.areacode
    5          where b.ms_type=0
    6     when NOT MATCHED then
    7          insert(msid,bill_month,areacode)
    8          values(b.msid,'200702',b.areacode)
    9          where b.ms_type=0;
    Done
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    905310001     200702      531       0.00
    SQL> insert into subs values(905360001,0,536);
    1 row inserted
    SQL> select * from subs;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905360001 0            536
    905310001 0            531
    905320001 1            532
    905330001 2            533
    SQL>
    SQL> merge into acct a
    2       using subs b on (a.msid=b.msid)
    3     when NOT MATCHED then
    4          insert(msid,bill_month,areacode)
    5          values(b.msid,'200702',b.areacode)
    6          where b.ms_type=0;
    Done
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    905310001     200702      531       0.00
    905360001     200702      536       0.00
    SQL> update subs set areacode=888 where ms_type=0;
    2 rows updated
    SQL> select * from subs;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905360001 0            888
    905310001 0            888
    905320001 1            532
    905330001 2            533
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    905310001     200702      531       0.00
    905360001     200702      536       0.00
    SQL>
    SQL> merge into acct a
    2       using subs b on (a.msid=b.msid)
    3     when MATCHED then
    4          update set a.areacode=b.areacode
    5          where b.ms_type=0;
    Done
    SQL> select * from acct;
    MSID BILL_MONTH AREACODE        FEE
    ---------- ---------- -------- ----------
    905310001     200702      888       0.00
    905360001     200702      888       0.00
    SQL>
    四、10g中增強(qiáng)二:刪除操作
    An optional DELETE WHERE clause can be used to clean up after a
    merge operation. Only those rows which match both the ON clause
    and the DELETE WHERE clause are deleted.
    merge into acct a
    using subs b on (a.msid=b.msid)
    when MATCHED then
    update set a.areacode=b.areacode
    delete where (b.ms_type!=0);
    SQL> select * from subs;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905310001 0            531
    905320001 1            532
    905330001 2            533
    SQL> select * from acct;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905310001 0            531
    905320001 1            532
    905330001 2            533
    SQL>
    SQL>  merge into acct a
    2       using subs b on (a.msid=b.msid)
    3     when MATCHED then
    4          update set a.areacode=b.areacode
    5          delete where (b.ms_type!=0);
    Done
    SQL> select * from acct;
    MSID MS_TYPE AREACODE
    ---------- ------- --------
    905310001 0            531
    SQL>
    更為詳盡的語(yǔ)法,請(qǐng)參考Oracle SQL Reference手冊(cè)!
    
    posted on 2009-08-25 21:42 xzc 閱讀(281) 評(píng)論(0)  編輯  收藏 所屬分類: Oracle
    主站蜘蛛池模板: 国产日韩AV免费无码一区二区| 美女视频黄免费亚洲| 91制片厂制作传媒免费版樱花 | 亚洲美女视频网站| 免费无码精品黄AV电影| 日本特黄特色AAA大片免费| 亚洲色图在线观看| 日韩免费视频在线观看| 国产精品网站在线观看免费传媒| 亚洲自国产拍揄拍| 亚洲精品成人网站在线观看| A级毛片内射免费视频| 野花香高清视频在线观看免费| 国产v亚洲v天堂a无| 国产亚洲色婷婷久久99精品| 天天摸天天碰成人免费视频| 两个人看的www高清免费观看| 亚洲熟女综合色一区二区三区| 国产亚洲精品观看91在线| 性xxxx视频播放免费| 日本免费污片中国特一级| 亚洲色中文字幕在线播放| 无码乱人伦一区二区亚洲一| 最新国产乱人伦偷精品免费网站| 亚洲中文字幕日本无线码| 国产V亚洲V天堂A无码| 四虎影视在线影院在线观看免费视频 | 最近免费视频中文字幕大全| 最新亚洲人成网站在线观看| 亚洲导航深夜福利| 亚洲AV无码一区二区二三区软件| 无码精品国产一区二区三区免费| mm1313亚洲国产精品无码试看 | a级毛片毛片免费观看久潮| 爱情岛论坛亚洲品质自拍视频网站 | 亚洲理论电影在线观看| 内射无码专区久久亚洲| 拍拍拍无挡视频免费观看1000| 久久无码av亚洲精品色午夜| 亚洲日产2021三区在线| 亚洲av日韩av无码|