处理Oracle分表的问题,需要为程序创建一个自动分表的存储过程,需要保证所有表结构,约束,索引等等一致。
说明:此Oracle为19c版本。
create or replace procedure COPYTABLE --存储过程名称
(tableName in varchar2, newTable in varchar2, dateStr in varchar2) --相关参数
authid current_user as --调用者权限
v_drop_table_sql varchar2(200); --
v_create_table_sql varchar2(4000); --
v_add_default_sql varchar2(4000); --
i_table_count number; --
cursor default_cols is --默认值游标
select COLUMN_NAME, DATA_DEFAULT --
from user_tab_columns --
where DATA_DEFAULT is not null --
and TABLE_NAME = tableName; --
v_add_primary_sql clob; --
cursor primary_cols is --主键游标,虽然主键只能有一个,但为统一起见还是用了游标
select distinct tmp.TABLE_NAME, --
tmp.INDEX_NAME, --
listagg(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; --
v_add_unique_sql clob; --唯一约束游标
cursor unique_cons is --
select distinct tmp.TABLE_NAME, --
tmp.INDEX_NAME, --
listagg(tmp.COLUMN_NAME) --
over(partition by tmp.TABLE_NAME, --
tmp.INDEX_NAME)) as uni_cols, --
replace(listagg(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; --
v_create_index_sql clob; --非唯一非主键索引游标
cursor normal_indexes is --
select distinct tmp.TABLE_NAME, --
tmp.INDEX_NAME, --
listagg(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; --
v_create_unique_index_sql clob; --不是由唯一约束生成的唯一索引游标
cursor unique_cols is --
select distinct tmp.TABLE_NAME, --
tmp.INDEX_NAME, --
listagg(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 --
execute immediate 'select count(*) from tabs where table_name = '''||newTable||'''' into i_table_count; --
if i_table_count > 0 then --
v_drop_table_sql := 'drop table '||newTable||' cascade constraints'; --
execute immediate v_drop_table_sql; --
end if; --
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 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; --
for c5 in normal_indexes loop --创建非主键且非唯一的索引,索引名字直接继承自主表,后缀dateStr以示不同
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 COPYTABLE; --