Oracle批次生成Merge指令碼程式

linxueguo發表於2021-09-07

生成merge into 指令碼

背景介紹:由於單表欄位數較多,生成的指令碼長度超過varchar2型別儲存上限,需要使用clob欄位儲存指令碼,且Dbms_Lob.Append不能用於sql語句中,需要建立臨時表處理

表命名規則:

源表tb,臨時表temp_tb

結果輸出到中間表test.temp_merge_sql

create table test.temp_merge_sql(
owner varchar2(128),    ----表屬主
table_name varchar2(128),    ----表名
key_col1 varchar2(256),        ----表主鍵
key_col2 varchar2(256),        ----merge條件
part1 varchar2(4000),        ----中間輸出
part2 varchar2(4000),        ----中間輸出
ouput_sql clob,           -----merge語句輸出
flag char(1));            ----處理情況

步驟:

1、向中間表 test.temp_merge_sql插入待生成指令碼的表清單(插入欄位owner,table_name)

Select *
  From test.temp_Merge_Sql
   For Update;

2、更新主鍵,merge條件

Update test.temp_Merge_Sql a
   Set a.Key_Col1 =
       (Select b.Pri_Key
          From (Select c.Owner Owner,
                       a.Constraint_Name,
                       c.Table_Name Table_Name,
                       Listagg(c.Column_Name, ',') Within Group(Order By c.Position) Pri_Key
                  From Dba_Constraints    a,
                       test.temp_Merge_Sql b,
                       Dba_Cons_Columns   c
                 Where a.Owner = b.Owner
                   And a.Table_Name = b.Table_Name
                   And c.Owner = b.Owner
                   And c.Table_Name = b.Table_Name
                   And c.Constraint_Name = a.Constraint_Name
                   And a.Constraint_Type = 'P'
                 Group By c.Owner, a.Constraint_Name, c.Table_Name) b
         Where a.Owner = b.Owner
           And a.Table_Name = b.Table_Name),
       a.Key_Col2 =
       (Select b.Pri_Key
          From (Select c.Owner Owner,
                       a.Constraint_Name,
                       c.Table_Name Table_Name,
                       Listagg('a.' || c.Column_Name || '=c.' ||
                               c.Column_Name,
                               ' and ') Within Group(Order By c.Position) Pri_Key
                  From Dba_Constraints    a,
                       test.temp_Merge_Sql b,
                       Dba_Cons_Columns   c
                 Where a.Owner = b.Owner
                   And a.Table_Name = b.Table_Name
                   And c.Owner = b.Owner
                   And c.Table_Name = b.Table_Name
                   And c.Constraint_Name = a.Constraint_Name
                   And a.Constraint_Type = 'P'
                 Group By c.Owner, a.Constraint_Name, c.Table_Name) b
         Where a.Owner = b.Owner
           And a.Table_Name = b.Table_Name)
 Where a.Flag Is Null
   And a.Key_Col1 Is Null;

3、生成merge指令碼

Declare
  v_Sql   Clob;
  v_Part1 Varchar2(4000);
  v_Part2 Varchar2(4000);
Begin
  For Cur In (Select a.Owner, a.Table_Name, a.Key_Col1, a.Key_Col2
                From test.temp_Merge_Sql a
               Where a.Flag Is Null
                 And a.Key_Col1 Is Not Null
                 And a.Key_Col2 Is Not Null)
  Loop
    Dbms_Lob.Createtemporary(v_Sql, True); ----初始化clob物件
    Select 'merge into ' || Cur.Owner || '.' || Cur.Table_Name ||
           ' a using (select * from ' || Cur.Owner || '.temp_' ||
           Cur.Table_Name || ')c on (' || Cur.Key_Col2 ||
           ') when matched then update set ' || Listagg(a.Col, ',') Within Group(Order By Column_Id)
      Into v_Part1
      From (Select 'a.' || Column_Name || '=c.' || Column_Name As Col,
                   'a.' || Column_Name As Col2,
                   'c.' || Column_Name As Col3,
                   Column_Id,
                   Table_Name
              From Dba_Tab_Cols
             Where Table_Name = Cur.Table_Name
               And Owner = Cur.Owner
               And Column_Name Not In
                   (Select Substr(Cur.Key_Col1 || ',',
                                  Decode(Level,
                                         1,
                                         0,
                                         Instr(Cur.Key_Col1 || ',',
                                               ',',
                                               1,
                                               Level - 1) + 1),
                                  Instr(Cur.Key_Col1 || ',', ',', 1, Level) -
                                  Decode(Level,
                                         1,
                                         0,
                                         Instr(Cur.Key_Col1 || ',',
                                               ',',
                                               1,
                                               Level - 1)) - 1)
                      From Dual
                    Connect By Level <=
                               Length(Cur.Key_Col1 || ',') -
                               Length(Replace(Cur.Key_Col1 || ',', ',', '')))
             Order By Column_Id) a
     Group By a.Table_Name;
    Select ' when not matched then insert(' || Listagg(a.Col2, ',') Within Group(Order By Column_Id) || ') values (' || Listagg(a.Col3, ',') Within Group(Order By Column_Id) || ');'
      Into v_Part2
      From (Select 'a.' || Column_Name || '=c.' || Column_Name As Col,
                   'a.' || Column_Name As Col2,
                   'c.' || Column_Name As Col3,
                   Column_Id,
                   Table_Name
              From Dba_Tab_Cols
             Where Table_Name = Cur.Table_Name
               And Owner = Cur.Owner
             Order By Column_Id) a
     Group By a.Table_Name;
    Dbms_Lob.Append(v_Sql, v_Part1);
    Dbms_Lob.Append(v_Sql, v_Part2);
    Update test.temp_Merge_Sql a
       Set (Part1, Part2, Ouput_Sql) =
           (Select v_Part1, v_Part2, v_Sql
              From Dual)
     Where a.Owner = Cur.Owner
       And a.Table_Name = Cur.Table_Name;
    Update test.temp_Merge_Sql a
       Set a.Flag = '1'
     Where a.Owner = Cur.Owner
       And a.Table_Name = Cur.Table_Name;
    Commit;
  End Loop;
End;
/

4、檢視輸出merge語句

 Select *
    From test.temp_Merge_Sql;


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31374736/viewspace-2790857/,如需轉載,請註明出處,否則將追究法律責任。

相關文章