Chinaunix首页 | 论坛 | 博客
  • 博客访问: 152367
  • 博文数量: 39
  • 博客积分: 825
  • 博客等级: 准尉
  • 技术积分: 955
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-25 14:05
文章分类

全部博文(39)

文章存档

2014年(4)

2013年(13)

2012年(22)

我的朋友

分类: 数据库开发技术

2014-05-16 18:36:45

项目中遇到的,对greenplum不是很熟悉,所以花了一天完成的东西,主要用来将
oracle的表定义信息转换成greenplum形式,可以实现批量化,不用powerdisger一
个个点了。

功能说明:

  将oracle的表(表结构定义、约束、默认值及分区信息)定义信息转换成greenplum
格式。

包说明:


点击(此处)折叠或打开

  1. create or replace package metadata_ora2gp as
  2.   function split(in_tablist in varchar2) return dbms_sql.varchar2a;
  3.   procedure convert_tab_create_ddl(in_tablist varchar2);
  4.   procedure convert_index_create_ddl(in_tablist varchar2);
  5.   procedure convert_constraint_ddl(in_tablist varchar2);
  6. end;
  7. /

包体:


点击(此处)折叠或打开

  1. create or replace package body metadata_ora2gp as

  2.   function split(in_tablist in varchar2) return dbms_sql.varchar2a as
  3.     v_tablist dbms_sql.varchar2a;
  4.   begin
  5.   
  6.     select distinct trim(regexp_substr(regexp_replace(in_tablist,
  7.                                                        '([^ .
  8. ]+) +|[.]([^ .
  9. ]+)',
  10.                                                        '\1.\2'),
  11.                                         '[^
  12. ]+',
  13.                                         1,
  14.                                         level)) bulk collect
  15.       into v_tablist
  16.       from dual
  17.     connect by level <= regexp_count(in_tablist, chr(10)) - 1;
  18.   
  19.     return v_tablist;
  20.   end split;

  21.   procedure convert_tab_create_ddl(in_tablist varchar2) as
  22.     /*
  23.       Author: Zhangyu@BI
  24.       CreateDate: 2014/05/14
  25.       Version: 1.0Beta
  26.       Function: convert oracle table create ddl to greenplum table create ddl.
  27.       
  28.       11g支持分区模式:RANGE-RANGE、LIST-RANGE、LIST-HASH和LIST-LIST。
  29.     */
  30.     v_dk varchar2(4000); --greenplum dk键
  31.     v_ddl_stmt clob; --ddl语句变量
  32.     v_tablist dbms_sql.varchar2a; --表名数组,格式为owner.table_name
  33.   
  34.     --列信息游标,包括字段类型、默认值及非空值等
  35.     cursor cur_collist(in_tab varchar2) is
  36.       select mtc.OWNER,
  37.              mtc.TABLE_NAME,
  38.              mtc.COLUMN_NAME,
  39.              mtc.DATA_TYPE,
  40.              mtc.DATA_LENGTH,
  41.              mtc.DATA_PRECISION,
  42.              mtc.DATA_SCALE,
  43.              mtc.NULLABLE,
  44.              mtc.COLUMN_ID,
  45.              replace(lower(mtc.DATA_DEFAULT), 'sysdate', 'current_date') as DATA_DEFAULT, --greenplum中没有sysdate函数
  46.              t.gp_type_name
  47.         from sys.my_tab_columns mtc, ORA2GP_TYPE_MAPPING t
  48.        where mtc.OWNER || '.' || mtc.TABLE_NAME in (upper(in_tab))
  49.          and mtc.DATA_TYPE = t.ora_type_name(+)
  50.        order by mtc.COLUMN_ID;
  51.   
  52.     type collist_tab is table of cur_collist%rowtype;
  53.     v_collist collist_tab;
  54.   
  55.     v_finalcol varchar2(32767); --存放单列信息的变量
  56.   
  57.     type part_rec is record(
  58.       col1 varchar2(4000),
  59.       col2 varchar2(4000));
  60.     type part_tab is table of part_rec;
  61.     v_part part_tab; --存放单个分区信息的数组
  62.   
  63.     v_partsql clob; --存放最终分区语句的变量
  64.   
  65.   begin
  66.     /************************************************************************************/
  67.     --拆分参数存放入表清单数组
  68.     /*
  69.       格式必须为:
  70.       owner.table_name
  71.       或者
  72.       owner table_name
  73.     */
  74.     v_tablist := metadata_ora2gp.split(in_tablist);
  75.   
  76.     /************************************************************************************/
  77.     --生成表定义语句
  78.   
  79.     for loop_idx in 1 .. v_tablist.count loop
  80.     
  81.       open cur_collist(v_tablist(loop_idx));
  82.     
  83.       if cur_collist%notfound then
  84.         v_collist := null;
  85.         dbms_output.put_line('Error: no ' || v_tablist(loop_idx) ||
  86.                              ' table.');
  87.       
  88.       else
  89.       
  90.         fetch cur_collist bulk collect
  91.           into v_collist;
  92.         close cur_collist;
  93.       
  94.       end if;
  95.     
  96.       for inner_idx in 1 .. v_collist.count loop
  97.       
  98.         --列映射转换
  99.         select v_collist(inner_idx).column_name || ' ' || case
  100.                   when v_collist(inner_idx)
  101.                    .data_type in ('VARCHAR2', 'NVARCHAR2', 'CHAR', 'NCHAR') then
  102.                    v_collist(inner_idx)
  103.                    .gp_type_name || '(' || v_collist(inner_idx).data_length || ')'
  104.                   when v_collist(inner_idx).data_type like 'TIMESTAMP%' then
  105.                    v_collist(inner_idx).data_type
  106.                   else
  107.                    v_collist(inner_idx).gp_type_name
  108.                 end || case
  109.                   when v_collist(inner_idx).nullable = 'N' then
  110.                    ' NOT NULL '
  111.                   else
  112.                    ' '
  113.                 end || case
  114.                   when v_collist(inner_idx).data_default is not null then
  115.                    ' DEFAULT ' || v_collist(inner_idx).data_default
  116.                   else
  117.                    ' '
  118.                 end
  119.           into v_finalcol
  120.           from dual;
  121.       
  122.         --拼接create table sql
  123.         if inner_idx = 1 then
  124.           if v_collist.count = 1 then
  125.             v_ddl_stmt := 'create table ' || v_collist(inner_idx).owner || '.' || v_collist(inner_idx)
  126.                          .table_name || '(' || v_finalcol || ')' || chr(10);
  127.           else
  128.             v_ddl_stmt := 'create table ' || v_collist(inner_idx).owner || '.' || v_collist(inner_idx)
  129.                          .table_name || '(' || v_finalcol || ',' || chr(10);
  130.           end if;
  131.         elsif inner_idx = v_collist.last then
  132.         
  133.           /************************************************************************************/
  134.           --生成distrubited key
  135.           <<DKGeneratedBlock>>
  136.           begin
  137.             with t as
  138.              (select listagg(dic.COLUMN_NAME, ',') within group(order by dic.COLUMN_POSITION) as collist,
  139.                      count(*) as col_cnt,
  140.                      min(count(*)) over() min_col_cnt
  141.                 from dba_indexes dc, dba_ind_columns dic
  142.                where dc.table_owner || '.' || dc.table_name in
  143.                      (upper(v_collist(inner_idx)
  144.                             .owner || '.' || v_collist(inner_idx).table_name))
  145.                  and dc.uniqueness = 'UNIQUE'
  146.                  and dc.owner = dic.INDEX_OWNER
  147.                  and dc.index_name = dic.INDEX_NAME
  148.                group by dic.INDEX_OWNER, dic.INDEX_NAME)
  149.             select ' DISTRIBUTED BY(' || collist || ') '
  150.               into v_dk
  151.               from t
  152.              where col_cnt = min_col_cnt;
  153.           
  154.           exception
  155.             when others then
  156.               v_dk := '';
  157.           end;
  158.           <<DKGeneratedBlock>>
  159.         
  160.           v_ddl_stmt := v_ddl_stmt || v_finalcol || ')' || chr(10) || v_dk;
  161.         else
  162.           v_ddl_stmt := v_ddl_stmt || v_finalcol || ',' || chr(10);
  163.         end if;
  164.       
  165.       end loop;
  166.       /************************************************************************************/
  167.       --生成分区语句
  168.       <<PartitionGeneratedBlock>>
  169.       begin
  170.       
  171.         with t1 as
  172.          (select dpt.partitioning_type, dpt.subpartitioning_type
  173.             from dba_part_tables dpt
  174.            where dpt.partitioning_type not in ('HASH')
  175.              and dpt.subpartitioning_type not in ('HASH')
  176.                 --gp默认是hash分区
  177.                 --缺陷:list-hash分区也被排除
  178.              and dpt.owner || '.' || dpt.table_name in
  179.                  (upper(v_tablist(loop_idx)))),
  180.         t2 as
  181.          (select listagg(dpkc.column_name, ',') within group(order by dpkc.column_position) pkcol
  182.             from dba_part_key_columns dpkc
  183.            where dpkc.owner || '.' || dpkc.name = upper(v_tablist(loop_idx))),
  184.         t3 as
  185.          (select listagg(dskc.column_name, ',') within group(order by dskc.column_position) spkcol
  186.             from dba_subpart_key_columns dskc
  187.            where dskc.owner || '.' || dskc.name = upper(v_tablist(loop_idx))),
  188.         t4 as
  189.          (select ' partition by ' || partitioning_type || '(' || pkcol || ')' ||
  190.                  chr(10) || ' subpartition by ' || subpartitioning_type || '(' ||
  191.                  spkcol || ')' part_col,
  192.                  t1.*,
  193.                  t2.*,
  194.                  t3.*
  195.             from t1
  196.             left outer join t2
  197.               on 1 = 1
  198.             left outer join t3
  199.               on 1 = 1),
  200.         t5 as
  201.          (select dtp.partition_name,
  202.                  dtp.partition_position,
  203.                  case
  204.                    when regexp_like(dtp.high_value, '^TO_DATE *[(]') then
  205.                     'timestamp ''' ||
  206.                     trim(regexp_substr(dtp.high_value, '[^'']+', 1, 2)) || ''''
  207.                    else
  208.                     dtp.high_value
  209.                  end as high_value, --修
  210.                  dtsp.partition_name as ppname,
  211.                  dtsp.subpartition_name,
  212.                  dtsp.subpartition_position,
  213.                  case
  214.                    when regexp_like(dtsp.high_value, '^TO_DATE *[(]') then
  215.                     'timestamp ''' ||
  216.                     trim(regexp_substr(dtsp.high_value, '[^'']+', 1, 2)) || ''''
  217.                    else
  218.                     dtsp.high_value
  219.                  end as sphval --修
  220.             from sys.my_tab_partitions dtp, sys.my_tab_subpartitions dtsp
  221.            where dtp.table_owner || '.' || dtp.table_name =
  222.                  upper(v_tablist(loop_idx))
  223.              and dtp.table_name = dtsp.table_name(+)
  224.              and dtp.table_owner = dtsp.table_owner(+)
  225.              and dtp.partition_name = dtsp.partition_name(+)),
  226.         t6 as
  227.          (select case
  228.                    when upper(high_value) in ('DEFAULT', 'MAXVALUE') then
  229.                     ' DEFAULT PARTITION other '
  230.                    else
  231.                     ' partition ' || partition_name || case
  232.                       when partitioning_type = 'RANGE' then
  233.                        ' start (' || high_value || ') INCLUSIVE '
  234.                       when partitioning_type = 'LIST' then
  235.                        ' values(' || high_value || ')'
  236.                       else
  237.                        null
  238.                     end
  239.                  end as p_key,
  240.                  case
  241.                    when upper(sphval) in ('DEFAULT', 'MAXVALUE') then
  242.                     ' DEFAULT SUBPARTITION other '
  243.                    else
  244.                     ' subpartition ' || subpartition_name || case
  245.                       when subpartitioning_type = 'RANGE' then
  246.                        ' start(' || sphval || ') INCLUSIVE'
  247.                       when subpartitioning_type = 'LIST' then
  248.                        ' values(' || sphval || ')'
  249.                       else
  250.                        null
  251.                     end
  252.                  end as sp_key,
  253.                  t4.*,
  254.                  t5.*
  255.             from t4, t5),
  256.         t7 as
  257.          (select lag(p_key) over(order by partition_position, subpartition_position) as lg_pkey,
  258.                  sp_key,
  259.                  partition_position,
  260.                  count(*) over() as cnt,
  261.                  row_number() over(order by partition_position, subpartition_position) row_cnt,
  262.                  count(subpartition_position) over(partition by partition_position) spcnt,
  263.                  subpartition_position,
  264.                  p_key,
  265.                  part_col
  266.             from t6),
  267.         t8 as
  268.          (select case
  269.                    when p_key = lg_pkey then
  270.                     null
  271.                    else
  272.                     p_key
  273.                  end as p_key,
  274.                  t7.sp_key,
  275.                  t7.cnt,
  276.                  t7.row_cnt,
  277.                  t7.spcnt,
  278.                  t7.partition_position,
  279.                  t7.subpartition_position,
  280.                  t7.part_col
  281.             from t7)
  282.         select regexp_replace(regexp_replace(case
  283.                                                when p_key is not null then
  284.                                                 p_key || chr(10) || '('
  285.                                                else
  286.                                                 null
  287.                                              end || case
  288.                                                when row_cnt = cnt then
  289.                                                 sp_key || ')' || chr(10)
  290.                                                when spcnt = subpartition_position then
  291.                                                 sp_key || '),' || chr(10)
  292.                                                else
  293.                                                 sp_key || ',' || chr(10)
  294.                                              end,
  295.                                              '[(] subpartition ,$',
  296.                                              ','),
  297.                               '[(] subpartition [)]$') key_list,
  298.                t8.part_col bulk collect
  299.           into v_part
  300.           from t8
  301.          order by partition_position, subpartition_position;
  302.       exception
  303.         when others then
  304.           v_part := null;
  305.       end;
  306.       <<PartitionGeneratedBlock>>
  307.     
  308.       for loop_idx in 1 .. v_part.count loop
  309.         v_partsql := v_partsql || v_part(loop_idx).col1;
  310.       end loop;
  311.     
  312.       if v_part.count <> 0 then
  313.       
  314.         v_partsql := regexp_replace(v_part(1).col2,
  315.                                     'subpartition by NONE[(][)]') ||
  316.                      chr(10) || '(' || chr(10) || v_partsql || ')';
  317.       else
  318.         v_part := null;
  319.       end if;
  320.     
  321.       /************************************************************************************/
  322.       --将分区语句拼接到sql中
  323.       v_ddl_stmt := v_ddl_stmt || v_partsql;
  324.     
  325.       dbms_output.put_line(v_ddl_stmt || ';');
  326.       v_partsql := '';
  327.     end loop;
  328.   
  329.   end convert_tab_create_ddl;

  330.   procedure convert_index_create_ddl(in_tablist in varchar2) as
  331.     /*
  332.       Author: Zhangyu@BI
  333.       CreateDate: 2014/05/14
  334.       Version: 1.0Beta
  335.       Function: convert oracle index create ddl to greenplum index create ddl.
  336.     */
  337.     v_idxlist dbms_sql.varchar2a;
  338.     v_tablist dbms_sql.varchar2a;
  339.   
  340.   begin
  341.     /************************************************************************************/
  342.     --拆分参数存放入表清单数组
  343.     /*
  344.       格式必须为:
  345.       owner.table_name
  346.       或者
  347.       owner table_name
  348.     */
  349.     v_tablist := metadata_ora2gp.split(in_tablist);
  350.   
  351.     for loop_idx in 1 .. v_tablist.count loop
  352.     
  353.       with t1 as
  354.        (select di.owner,
  355.                di.index_name,
  356.                di.uniqueness,
  357.                di.index_type,
  358.                dic.COLUMN_NAME,
  359.                partitioned,
  360.                di.table_owner,
  361.                di.table_name,
  362.                dic.COLUMN_POSITION,
  363.                ' ' DESCEND --gp中无升降概念
  364.           from dba_indexes di, dba_ind_columns dic
  365.          where di.owner = dic.INDEX_OWNER
  366.            and di.index_name = dic.INDEX_NAME
  367.            and di.table_owner || '.' || di.table_name in
  368.                (upper(v_tablist(loop_idx)))
  369.            and di.index_type not like 'FUNCTION-BASED%'),
  370.       t2 as
  371.        (select owner,
  372.                index_name,
  373.                uniqueness,
  374.                table_owner,
  375.                partitioned,
  376.                table_name,
  377.                index_type,
  378.                listagg(COLUMN_NAME || ' ' || DESCEND, ',') within group(order by COLUMN_POSITION) collist
  379.           from t1
  380.          group by owner,
  381.                   index_name,
  382.                   uniqueness,
  383.                   index_type,
  384.                   partitioned,
  385.                   table_owner,
  386.                   table_name)
  387.       select 'create ' || case
  388.                 when index_type = 'BITMAP' then
  389.                 
  390.                  index_type
  391.                 when uniqueness = 'UNIQUE' then
  392.                  uniqueness
  393.                 else
  394.                  null
  395.               end || ' index ' || t2.index_name || ' on ' ||
  396.               table_owner || '.' || t2.table_name || '(' || collist || ') ' ||
  397.              --dpi.locality
  398.               ';' as idx_crtsql bulk collect
  399.         into v_idxlist
  400.         from t2, dba_part_indexes dpi
  401.        where t2.owner = dpi.owner(+)
  402.          and t2.index_name = dpi.index_name(+);
  403.     
  404.       for loop_idx in 1 .. v_idxlist.count loop
  405.         dbms_output.put_line(v_idxlist(loop_idx));
  406.       end loop;
  407.     
  408.     end loop;
  409.   
  410.   end convert_index_create_ddl;

  411.   procedure convert_constraint_ddl(in_tablist varchar2) as
  412.     /*
  413.       Author: Zhangyu@BI
  414.       CreateDate: 2014/05/14
  415.       Version: 1.0Beta
  416.       Function: convert oracle index create ddl to greenplum index create ddl.
  417.     */
  418.     v_conslist dbms_sql.varchar2a;
  419.     v_tablist dbms_sql.varchar2a;
  420.   
  421.   begin
  422.     /************************************************************************************/
  423.     --拆分参数存放入表清单数组
  424.     /*
  425.       格式必须为:
  426.       owner.table_name
  427.       或者
  428.       owner table_name
  429.     */
  430.     v_tablist := metadata_ora2gp.split(in_tablist);
  431.   
  432.     for loop_idx in 1 .. v_tablist.count loop
  433.     
  434.       with t as
  435.        (
  436.         --check约束
  437.         select 'alter table ' || dc.owner || '.' || dc.table_name ||
  438.                 ' add constraint ' || dc.constraint_name || ' check (' ||
  439.                 replace(dc.search_condition,'"') || ');' as cons_ddl
  440.           from sys.my_constraints dc
  441.          where dc.constraint_type in ('C')
  442.            and dc.status = 'ENABLED'
  443.            and dc.owner || '.' || dc.table_name = upper(v_tablist(loop_idx))
  444.         union all
  445.         --reference约束
  446.         select 'alter table ' || dc.owner || '.' || dc.table_name ||
  447.                 ' add constraint ' || dc.constraint_name || ' foreign key(' ||
  448.                 collist || ') references ' || dc.r_owner || '.' ||
  449.                 dc1.table_name || ';'
  450.           from sys.my_constraints dc,
  451.                 (select dcc.owner,
  452.                         dcc.constraint_name,
  453.                         dcc.table_name,
  454.                         listagg(column_name, ',') within group(order by dcc.position) as collist
  455.                    from dba_cons_columns dcc
  456.                   group by dcc.owner, dcc.constraint_name, dcc.table_name) cons_col,
  457.                 sys.my_constraints dc1
  458.          where dc.constraint_type in ('R')
  459.            and dc.status = 'ENABLED'
  460.            and dc.owner = cons_col.owner
  461.            and dc.table_name = cons_col.table_name
  462.            and dc.constraint_name = cons_col.constraint_name
  463.            and dc.r_owner = dc1.owner
  464.            and dc.r_constraint_name = dc1.constraint_name
  465.            and dc.owner || '.' || dc.table_name = upper(v_tablist(loop_idx))
  466.         union all
  467.         --unique约束
  468.         select 'alter table ' || dc.owner || '.' || dc.table_name ||
  469.                 ' add constraint ' || dc.constraint_name || ' unique(' ||
  470.                 collist || ');'
  471.           from sys.my_constraints dc,
  472.                 (select dcc.owner,
  473.                         dcc.constraint_name,
  474.                         dcc.table_name,
  475.                         listagg(column_name, ',') within group(order by dcc.position) as collist
  476.                    from dba_cons_columns dcc
  477.                   group by dcc.owner, dcc.constraint_name, dcc.table_name) cons_col
  478.          where dc.constraint_type in ('U')
  479.            and dc.status = 'ENABLED'
  480.            and dc.owner = cons_col.owner
  481.            and dc.table_name = cons_col.table_name
  482.            and dc.constraint_name = cons_col.constraint_name
  483.            and dc.owner || '.' || dc.table_name = upper(v_tablist(loop_idx))
  484.         union all
  485.         --primary约束
  486.         select 'alter table ' || dc.owner || '.' || dc.table_name ||
  487.                 ' add constraint ' || dc.constraint_name || ' primary key(' ||
  488.                 collist || ');'
  489.           from sys.my_constraints dc,
  490.                 (select dcc.owner,
  491.                         dcc.constraint_name,
  492.                         dcc.table_name,
  493.                         listagg(column_name, ',') within group(order by dcc.position) as collist
  494.                    from dba_cons_columns dcc
  495.                   group by dcc.owner, dcc.constraint_name, dcc.table_name) cons_col
  496.          where dc.constraint_type in ('P')
  497.            and dc.status = 'ENABLED'
  498.            and dc.owner = cons_col.owner
  499.            and dc.table_name = cons_col.table_name
  500.            and dc.owner || '.' || dc.table_name = upper(v_tablist(loop_idx))
  501.            and dc.constraint_name = cons_col.constraint_name)
  502.       select * bulk collect into v_conslist from t;
  503.     
  504.       for loop_idx in 1 .. v_conslist.count loop
  505.         dbms_output.put_line(v_conslist(loop_idx));
  506.       end loop;
  507.     end loop;
  508.   
  509.   end convert_constraint_ddl;
  510. end metadata_ora2gp;
  511. /


阅读(8776) | 评论(0) | 转发(0) |
0

上一篇:列转行与行转列

下一篇:没有了

给主人留下些什么吧!~~