Oracle完全復制表結構的存儲過程


最近在處理一個分表的問題時,需要為程序創建一個自動分表的存儲過程,需要保證所有表結構,約束,索引等等一致,此外視圖,存儲過程,權限等等問題暫不用考慮。

在Mysql中,創建分表的存儲過程,相當簡單:create table if not exists <new_table_name> like <old_table_name>;即可,約束,索引一應俱全。

但是在Oracle中貌似沒有,所以只能自己寫,需要考慮的情況比較多,腳本如下:

CREATE OR REPLACE PROCEDURE CREATETABLE(tableName in varchar2,
                                        dateStr   in varchar2)
  AUTHID CURRENT_USER as
  newTable varchar2(32) := tableName || '_' || dateStr;

  v_create_table_sql clob;
  --c1,默認值游標
  v_add_default_sql clob;
  cursor default_cols is
    select COLUMN_NAME, DATA_DEFAULT
      from user_tab_columns
     where DATA_DEFAULT is not null
       and TABLE_NAME = tableName;
  --c2 主鍵的not null不會繼承,但not null約束的會繼承,因此c2全部注釋
  /*v_add_notnull_sql clob;
  cursor notnull_cols is select COLUMN_NAME from user_tab_columns t where t.NULLABLE='N' and  and t.TABLE_NAME=tableName;*/
  --c3,主鍵游標,雖然主鍵只能有一個,但為統一起見還是用了游標
  v_add_primary_sql clob;
  cursor primary_cols is
    select distinct tmp.TABLE_NAME,
                    tmp.INDEX_NAME,
                    to_char(wm_concat(tmp.COLUMN_NAME)
                            over(partition by tmp.TABLE_NAME)) as pri_cols
      from (select i.TABLE_NAME,
                   i.INDEX_NAME,
                   i.COLUMN_NAME,
                   i.COLUMN_POSITION
              from user_ind_columns i
              join user_constraints c
                on i.INDEX_NAME = c.index_name
             where c.CONSTRAINT_TYPE = 'P'
               and i.TABLE_NAME = tableName
             order by 1, 2, 4) tmp;
  --c4,唯一約束游標
  v_add_unique_sql clob;
  cursor unique_cons is
    select distinct tmp.TABLE_NAME,
                    tmp.INDEX_NAME,
                    to_char(wm_concat(tmp.COLUMN_NAME)
                            over(partition by tmp.TABLE_NAME,
                                 tmp.INDEX_NAME)) as uni_cols,
                    replace(to_char(wm_concat(tmp.COLUMN_NAME)
                                    over(partition by tmp.INDEX_NAME)),
                            ',',
                            '_') as new_indexname
      from (select i.TABLE_NAME,
                   i.INDEX_NAME,
                   i.COLUMN_NAME,
                   i.COLUMN_POSITION
              from user_ind_columns i
              join user_constraints c
                on i.INDEX_NAME = c.index_name
             where c.CONSTRAINT_TYPE = 'U'
               and i.TABLE_NAME = tableName
             order by 1, 2, 4) tmp;
  --c5,非唯一非主鍵索引游標
  v_create_index_sql clob;
  cursor normal_indexes is
    select distinct tmp.TABLE_NAME,
                    tmp.INDEX_NAME,
                    to_char(wm_concat(tmp.COLUMN_NAME)
                            over(partition by tmp.TABLE_NAME,
                                 tmp.INDEX_NAME)) as index_cols
      from (select i.TABLE_NAME,
                   i.INDEX_NAME,
                   c.COLUMN_NAME,
                   c.COLUMN_POSITION
              from user_indexes i
              join user_ind_columns c
                on i.INDEX_NAME = c.INDEX_NAME
             where index_type = 'NORMAL'
               and i.TABLE_NAME = tableName
               and i.uniqueness = 'NONUNIQUE'
             order by 1, 2, 4) tmp;
  --c6,不是由唯一約束生成的唯一索引游標
  v_create_unique_index_sql clob;
  cursor unique_cols is
    select distinct tmp.TABLE_NAME,
                    tmp.INDEX_NAME,
                    to_char(wm_concat(tmp.COLUMN_NAME)
                            over(partition by tmp.TABLE_NAME,
                                 tmp.INDEX_NAME)) as index_cols
      from (select u_i.TABLE_NAME,
                   u_i.INDEX_NAME,
                   c.COLUMN_NAME,
                   c.COLUMN_POSITION
              from (select *
                      from user_indexes
                     where table_name = tableName
                       and index_type = 'NORMAL'
                       and index_name not in
                           (select index_name
                              from user_constraints
                             where table_name = tableName
                               and index_name is not null)) u_i
              join user_ind_columns c
                on u_i.INDEX_NAME = c.INDEX_NAME
             where u_i.TABLE_NAME = tableName
               and u_i.uniqueness = 'UNIQUE'
             order by 1, 2, 4) tmp;
begin
  --創建表結構
  v_create_table_sql := 'create table ' || newTable || ' as select * from ' ||
                        tableName || ' where 1=2';
  execute immediate v_create_table_sql;
  --添加默認值
  for c1 in default_cols loop
    v_add_default_sql := 'alter table ' || newTable || ' modify ' ||
                         c1.column_name || ' default ' || c1.DATA_DEFAULT;
    execute immediate v_add_default_sql;
  end loop;
  --添加非空約束
  /*  for c2 in notnull_cols loop
    v_add_notnull_sql:='alter table '||newTable||' modify '||c2.column_name||' not null';
    execute immediate v_add_notnull_sql;
  end loop;*/
  --添加主鍵約束
  for c3 in primary_cols loop
    v_add_primary_sql := 'alter table ' || newTable ||
                         ' add constraint Pk_' || newTable ||
                         ' primary key(' || c3.pri_cols || ')';
    execute immediate v_add_primary_sql;
  end loop;
  --添加唯一性約束,由於原約束名可能由於創建約束的方法不同,存在系統自定義的名字,因此這里直接命名唯一約束
  for c4 in unique_cons loop
    v_add_unique_sql := 'alter table ' || newTable || ' add constraint U_' ||
                        c4.new_indexname || ' unique(' || c4.uni_cols || ')';
    execute immediate v_add_unique_sql;
  end loop;
  --創建非主鍵且非唯一的索引,索引名字直接繼承自主表,后綴dateStr以示不同
  for c5 in normal_indexes loop
    v_create_index_sql := 'create index ' || c5.index_name || '_' ||
                          dateStr || ' on ' || newTable || '(' ||
                          c5.index_cols || ')';
    execute immediate v_create_index_sql;
  end loop;
  --創建不是由於約束生成的唯一索引
  for c6 in unique_cols loop
    v_create_unique_index_sql := 'create unique index ' || c6.index_name || '_' ||
                                 dateStr || ' on ' || newTable || '(' ||
                                 c6.index_cols || ')';
    execute immediate v_create_unique_index_sql;
  end loop;
end createTable;

/

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM