oracle 集合di,oracle转greenplum功能实现

create or replace package body metadata_ora2gp as

function split(in_tablist in varchar2) return dbms_sql.varchar2a as

v_tablist dbms_sql.varchar2a;

begin

select distinct trim(regexp_substr(regexp_replace(in_tablist,

'([^ .

]+) +|[.]([^ .

]+)',

'\1.\2'),

'[^

]+',

1,

level)) bulk collect

into v_tablist

from dual

connect by level <= regexp_count(in_tablist, chr(10)) - 1;

return v_tablist;

end split;

procedure convert_tab_create_ddl(in_tablist varchar2) as

/*

Author: Zhangyu@BI

CreateDate: 2014/05/14

Version: 1.0Beta

Function: convert oracle table create ddl to greenplum table create ddl.

11g支持分区模式:RANGE-RANGE、LIST-RANGE、LIST-HASH和LIST-LIST。

*/

v_dk varchar2(4000); --greenplum dk键

v_ddl_stmt clob; --ddl语句变量

v_tablist dbms_sql.varchar2a; --表名数组,格式为owner.table_name

--列信息游标,包括字段类型、默认值及非空值等

cursor cur_collist(in_tab varchar2) is

select mtc.OWNER,

mtc.TABLE_NAME,

mtc.COLUMN_NAME,

mtc.DATA_TYPE,

mtc.DATA_LENGTH,

mtc.DATA_PRECISION,

mtc.DATA_SCALE,

mtc.NULLABLE,

mtc.COLUMN_ID,

replace(lower(mtc.DATA_DEFAULT), 'sysdate', 'current_date') as DATA_DEFAULT, --greenplum中没有sysdate函数

t.gp_type_name

from sys.my_tab_columns mtc, ORA2GP_TYPE_MAPPING t

where mtc.OWNER || '.' || mtc.TABLE_NAME in (upper(in_tab))

and mtc.DATA_TYPE = t.ora_type_name(+)

order by mtc.COLUMN_ID;

type collist_tab is table of cur_collist%rowtype;

v_collist collist_tab;

v_finalcol varchar2(32767); --存放单列信息的变量

type part_rec is record(

col1 varchar2(4000),

col2 varchar2(4000));

type part_tab is table of part_rec;

v_part part_tab; --存放单个分区信息的数组

v_partsql clob; --存放最终分区语句的变量

begin

/************************************************************************************/

--拆分参数存放入表清单数组

/*

格式必须为:

owner.table_name

或者

owner table_name

*/

v_tablist := metadata_ora2gp.split(in_tablist);

/************************************************************************************/

--生成表定义语句

for loop_idx in 1 .. v_tablist.count loop

open cur_collist(v_tablist(loop_idx));

if cur_collist%notfound then

v_collist := null;

dbms_output.put_line('Error: no ' || v_tablist(loop_idx) ||

' table.');

else

fetch cur_collist bulk collect

into v_collist;

close cur_collist;

end if;

for inner_idx in 1 .. v_collist.count loop

--列映射转换

select v_collist(inner_idx).column_name || ' ' || case

when v_collist(inner_idx)

.data_type in ('VARCHAR2', 'NVARCHAR2', 'CHAR', 'NCHAR') then

v_collist(inner_idx)

.gp_type_name || '(' || v_collist(inner_idx).data_length || ')'

when v_collist(inner_idx).data_type like 'TIMESTAMP%' then

v_collist(inner_idx).data_type

else

v_collist(inner_idx).gp_type_name

end || case

when v_collist(inner_idx).nullable = 'N' then

' NOT NULL '

else

' '

end || case

when v_collist(inner_idx).data_default is not null then

' DEFAULT ' || v_collist(inner_idx).data_default

else

' '

end

into v_finalcol

from dual;

--拼接create table sql

if inner_idx = 1 then

if v_collist.count = 1 then

v_ddl_stmt := 'create table ' || v_collist(inner_idx).owner || '.' || v_collist(inner_idx)

.table_name || '(' || v_finalcol || ')' || chr(10);

else

v_ddl_stmt := 'create table ' || v_collist(inner_idx).owner || '.' || v_collist(inner_idx)

.table_name || '(' || v_finalcol || ',' || chr(10);

end if;

elsif inner_idx = v_collist.last then

/************************************************************************************/

--生成distrubited key

<>

begin

with t as

(select listagg(dic.COLUMN_NAME, ',') within group(order by dic.COLUMN_POSITION) as collist,

count(*) as col_cnt,

min(count(*)) over() min_col_cnt

from dba_indexes dc, dba_ind_columns dic

where dc.table_owner || '.' || dc.table_name in

(upper(v_collist(inner_idx)

.owner || '.' || v_collist(inner_idx).table_name))

and dc.uniqueness = 'UNIQUE'

and dc.owner = dic.INDEX_OWNER

and dc.index_name = dic.INDEX_NAME

group by dic.INDEX_OWNER, dic.INDEX_NAME)

select ' DISTRIBUTED BY(' || collist || ') '

into v_dk

from t

where col_cnt = min_col_cnt;

exception

when others then

v_dk := '';

end;

<>

v_ddl_stmt := v_ddl_stmt || v_finalcol || ')' || chr(10) || v_dk;

else

v_ddl_stmt := v_ddl_stmt || v_finalcol || ',' || chr(10);

end if;

end loop;

/************************************************************************************/

--生成分区语句

<>

begin

with t1 as

(select dpt.partitioning_type, dpt.subpartitioning_type

from dba_part_tables dpt

where dpt.partitioning_type not in ('HASH')

and dpt.subpartitioning_type not in ('HASH')

--gp默认是hash分区

--缺陷:list-hash分区也被排除

and dpt.owner || '.' || dpt.table_name in

(upper(v_tablist(loop_idx)))),

t2 as

(select listagg(dpkc.column_name, ',') within group(order by dpkc.column_position) pkcol

from dba_part_key_columns dpkc

where dpkc.owner || '.' || dpkc.name = upper(v_tablist(loop_idx))),

t3 as

(select listagg(dskc.column_name, ',') within group(order by dskc.column_position) spkcol

from dba_subpart_key_columns dskc

where dskc.owner || '.' || dskc.name = upper(v_tablist(loop_idx))),

t4 as

(select ' partition by ' || partitioning_type || '(' || pkcol || ')' ||

chr(10) || ' subpartition by ' || subpartitioning_type || '(' ||

spkcol || ')' part_col,

t1.*,

t2.*,

t3.*

from t1

left outer join t2

on 1 = 1

left outer join t3

on 1 = 1),

t5 as

(select dtp.partition_name,

dtp.partition_position,

case

when regexp_like(dtp.high_value, '^TO_DATE *[(]') then

'timestamp ''' ||

trim(regexp_substr(dtp.high_value, '[^'']+', 1, 2)) || ''''

else

dtp.high_value

end as high_value, --修

dtsp.partition_name as ppname,

dtsp.subpartition_name,

dtsp.subpartition_position,

case

when regexp_like(dtsp.high_value, '^TO_DATE *[(]') then

'timestamp ''' ||

trim(regexp_substr(dtsp.high_value, '[^'']+', 1, 2)) || ''''

else

dtsp.high_value

end as sphval --修

from sys.my_tab_partitions dtp, sys.my_tab_subpartitions dtsp

where dtp.table_owner || '.' || dtp.table_name =

upper(v_tablist(loop_idx))

and dtp.table_name = dtsp.table_name(+)

and dtp.table_owner = dtsp.table_owner(+)

and dtp.partition_name = dtsp.partition_name(+)),

t6 as

(select case

when upper(high_value) in ('DEFAULT', 'MAXVALUE') then

' DEFAULT PARTITION other '

else

' partition ' || partition_name || case

when partitioning_type = 'RANGE' then

' start (' || high_value || ') INCLUSIVE '

when partitioning_type = 'LIST' then

' values(' || high_value || ')'

else

null

end

end as p_key,

case

when upper(sphval) in ('DEFAULT', 'MAXVALUE') then

' DEFAULT SUBPARTITION other '

else

' subpartition ' || subpartition_name || case

when subpartitioning_type = 'RANGE' then

' start(' || sphval || ') INCLUSIVE'

when subpartitioning_type = 'LIST' then

' values(' || sphval || ')'

else

null

end

end as sp_key,

t4.*,

t5.*

from t4, t5),

t7 as

(select lag(p_key) over(order by partition_position, subpartition_position) as lg_pkey,

sp_key,

partition_position,

count(*) over() as cnt,

row_number() over(order by partition_position, subpartition_position) row_cnt,

count(subpartition_position) over(partition by partition_position) spcnt,

subpartition_position,

p_key,

part_col

from t6),

t8 as

(select case

when p_key = lg_pkey then

null

else

p_key

end as p_key,

t7.sp_key,

t7.cnt,

t7.row_cnt,

t7.spcnt,

t7.partition_position,

t7.subpartition_position,

t7.part_col

from t7)

select regexp_replace(regexp_replace(case

when p_key is not null then

p_key || chr(10) || '('

else

null

end || case

when row_cnt = cnt then

sp_key || ')' || chr(10)

when spcnt = subpartition_position then

sp_key || '),' || chr(10)

else

sp_key || ',' || chr(10)

end,

'[(] subpartition ,$',

','),

'[(] subpartition [)]$') key_list,

t8.part_col bulk collect

into v_part

from t8

order by partition_position, subpartition_position;

exception

when others then

v_part := null;

end;

<>

for loop_idx in 1 .. v_part.count loop

v_partsql := v_partsql || v_part(loop_idx).col1;

end loop;

if v_part.count <> 0 then

v_partsql := regexp_replace(v_part(1).col2,

'subpartition by NONE[(][)]') ||

chr(10) || '(' || chr(10) || v_partsql || ')';

else

v_part := null;

end if;

/************************************************************************************/

--将分区语句拼接到sql中

v_ddl_stmt := v_ddl_stmt || v_partsql;

dbms_output.put_line(v_ddl_stmt || ';');

v_partsql := '';

end loop;

end convert_tab_create_ddl;

procedure convert_index_create_ddl(in_tablist in varchar2) as

/*

Author: Zhangyu@BI

CreateDate: 2014/05/14

Version: 1.0Beta

Function: convert oracle index create ddl to greenplum index create ddl.

*/

v_idxlist dbms_sql.varchar2a;

v_tablist dbms_sql.varchar2a;

begin

/************************************************************************************/

--拆分参数存放入表清单数组

/*

格式必须为:

owner.table_name

或者

owner table_name

*/

v_tablist := metadata_ora2gp.split(in_tablist);

for loop_idx in 1 .. v_tablist.count loop

with t1 as

(select di.owner,

di.index_name,

di.uniqueness,

di.index_type,

dic.COLUMN_NAME,

partitioned,

di.table_owner,

di.table_name,

dic.COLUMN_POSITION,

' ' DESCEND --gp中无升降概念

from dba_indexes di, dba_ind_columns dic

where di.owner = dic.INDEX_OWNER

and di.index_name = dic.INDEX_NAME

and di.table_owner || '.' || di.table_name in

(upper(v_tablist(loop_idx)))

and di.index_type not like 'FUNCTION-BASED%'),

t2 as

(select owner,

index_name,

uniqueness,

table_owner,

partitioned,

table_name,

index_type,

listagg(COLUMN_NAME || ' ' || DESCEND, ',') within group(order by COLUMN_POSITION) collist

from t1

group by owner,

index_name,

uniqueness,

index_type,

partitioned,

table_owner,

table_name)

select 'create ' || case

when index_type = 'BITMAP' then

index_type

when uniqueness = 'UNIQUE' then

uniqueness

else

null

end || ' index ' || t2.index_name || ' on ' ||

table_owner || '.' || t2.table_name || '(' || collist || ') ' ||

--dpi.locality

';' as idx_crtsql bulk collect

into v_idxlist

from t2, dba_part_indexes dpi

where t2.owner = dpi.owner(+)

and t2.index_name = dpi.index_name(+);

for loop_idx in 1 .. v_idxlist.count loop

dbms_output.put_line(v_idxlist(loop_idx));

end loop;

end loop;

end convert_index_create_ddl;

procedure convert_constraint_ddl(in_tablist varchar2) as

/*

Author: Zhangyu@BI

CreateDate: 2014/05/14

Version: 1.0Beta

Function: convert oracle index create ddl to greenplum index create ddl.

*/

v_conslist dbms_sql.varchar2a;

v_tablist dbms_sql.varchar2a;

begin

/************************************************************************************/

--拆分参数存放入表清单数组

/*

格式必须为:

owner.table_name

或者

owner table_name

*/

v_tablist := metadata_ora2gp.split(in_tablist);

for loop_idx in 1 .. v_tablist.count loop

with t as

(

--check约束

select 'alter table ' || dc.owner || '.' || dc.table_name ||

' add constraint ' || dc.constraint_name || ' check (' ||

replace(dc.search_condition,'"') || ');' as cons_ddl

from sys.my_constraints dc

where dc.constraint_type in ('C')

and dc.status = 'ENABLED'

and dc.owner || '.' || dc.table_name = upper(v_tablist(loop_idx))

union all

--reference约束

select 'alter table ' || dc.owner || '.' || dc.table_name ||

' add constraint ' || dc.constraint_name || ' foreign key(' ||

collist || ') references ' || dc.r_owner || '.' ||

dc1.table_name || ';'

from sys.my_constraints dc,

(select dcc.owner,

dcc.constraint_name,

dcc.table_name,

listagg(column_name, ',') within group(order by dcc.position) as collist

from dba_cons_columns dcc

group by dcc.owner, dcc.constraint_name, dcc.table_name) cons_col,

sys.my_constraints dc1

where dc.constraint_type in ('R')

and dc.status = 'ENABLED'

and dc.owner = cons_col.owner

and dc.table_name = cons_col.table_name

and dc.constraint_name = cons_col.constraint_name

and dc.r_owner = dc1.owner

and dc.r_constraint_name = dc1.constraint_name

and dc.owner || '.' || dc.table_name = upper(v_tablist(loop_idx))

union all

--unique约束

select 'alter table ' || dc.owner || '.' || dc.table_name ||

' add constraint ' || dc.constraint_name || ' unique(' ||

collist || ');'

from sys.my_constraints dc,

(select dcc.owner,

dcc.constraint_name,

dcc.table_name,

listagg(column_name, ',') within group(order by dcc.position) as collist

from dba_cons_columns dcc

group by dcc.owner, dcc.constraint_name, dcc.table_name) cons_col

where dc.constraint_type in ('U')

and dc.status = 'ENABLED'

and dc.owner = cons_col.owner

and dc.table_name = cons_col.table_name

and dc.constraint_name = cons_col.constraint_name

and dc.owner || '.' || dc.table_name = upper(v_tablist(loop_idx))

union all

--primary约束

select 'alter table ' || dc.owner || '.' || dc.table_name ||

' add constraint ' || dc.constraint_name || ' primary key(' ||

collist || ');'

from sys.my_constraints dc,

(select dcc.owner,

dcc.constraint_name,

dcc.table_name,

listagg(column_name, ',') within group(order by dcc.position) as collist

from dba_cons_columns dcc

group by dcc.owner, dcc.constraint_name, dcc.table_name) cons_col

where dc.constraint_type in ('P')

and dc.status = 'ENABLED'

and dc.owner = cons_col.owner

and dc.table_name = cons_col.table_name

and dc.owner || '.' || dc.table_name = upper(v_tablist(loop_idx))

and dc.constraint_name = cons_col.constraint_name)

select * bulk collect into v_conslist from t;

for loop_idx in 1 .. v_conslist.count loop

dbms_output.put_line(v_conslist(loop_idx));

end loop;

end loop;

end convert_constraint_ddl;

end metadata_ora2gp;

/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值