数据库设计文档DBMS以及字符集的快速转换

来源:互联网 发布:会员卡管理系统 php 编辑:程序博客网 时间:2024/06/03 19:04

     今天PMO下达任务单,校讯通数据库从sybase系统改造到oracle系统,进行了对象的总计有312张实体表,20个过程,通过手工敲,那肯定是猴年马月的事情,不符合项目任务的工期进度。以下是本次转化的快捷方法:

     1、通过powerdesigner的Change Current DBMS操作。

new dbms 选择ORACLE Version 10gR2替换current dbms的Sybase AS Enterprise 12.5.3a。

符合期望的:通过此步操作char、varchar、numeric、datetime转向了我们期望的char、varchar2、number、date。

不符合期望的:integer没有转向我们期望的number,默认值getdate()没有转向我们期望的SYSDATE,default ''没有转为有效的default ' '。针对oracle 空串是无效的。索引名保留了sybase特性,对象中唯一,却没有符合oracle的全局唯一。过程那是原原本本保留了sybase的脚本。

     2、开始针对不符合期望的改造工作

校讯通数据库设计文档是用powerdesigner15版本设计的,可以直接通过编辑工具editplus,UltraEdit打开,本质上是xml文件,然后查找integer类型定义关键字串。

      类型定义:<a:DataType>INTEGER</a:DataType>  统一修改成了 <a:DataType>NUMBER(10)</a:DataType>。

      针对本质是布尔类型,是和否的判断的,显然NUMBER(1)就行,在定义此类字段名时有显著特征is_开头,通过EltraEdit打开找到<a:Code>is_字符串,在此字符串附近定位到针对这个字段的类型定义,由于做了前面步骤,都已经改成了NUMBER(10)统一改为NUMBER(1),针对其他字段,虽然可能有的字段长度不需要10,个别对待修改。

      默认值定义:<a:DefaultValue>getdate()</a:DefaultValue>统一修改成了<a:DefaultValue>SYSDATE</a:DefaultValue>,在sybase中的default ''后来经分析确认,通过编辑工具打xml真实定义是<a:DefaultValue>&#39;&#39;</a:DefaultValue>统一修改成了<a:DefaultValue>&#39; &#39;</a:DefaultValue>中间加入一空格,Oracle可以支持。

      做了以上两步之后,表对象定义的类型以及默认值都符合了期望,至于索引名称由于要全局唯一,只能通过手工修改了,包括过程也是。通过统一替换已经给我们节省了不少时间,赶上项目任务单的计划进度不成问题了。其他类型的数据库设计文档的DBMS转换可以参考类似。

修改的规范参见我的blog:数据库设计规范

http://blog.csdn.net/xujinyang/article/details/6977149


       3、针对原设计文档gbk字符集转为utf8的修改

通过分析gbk字符集转为utf8主要焦点是针对varchar2类型的字段长度原理上以1.5倍扩展,因为gbk字符集特殊字符以及汉字类占两个字节,而utf8占3个字节,为此特编写了两个过程:

1)针对数据库设计文档pdm的修改过程:up_modify_pdm

CREATE OR REPLACE PROCEDURE up_modify_pdm
(
var_filepath   IN   varchar2,
var_filename   IN   varchar2,
var_maxnum   IN   NUMBER
)
is
var_in_str VARCHAR2(32767);
var_out_str VARCHAR2(32767);  
var_in_file UTL_FILE.FILE_TYPE;
var_out_file UTL_FILE.FILE_TYPE;
var_i number:=0;
var_j number:=0;
var_len varchar2(10);  
begin
  var_in_file := UTL_FILE.FOPEN(var_filepath,var_filename,'R',var_maxnum);
var_out_file:= UTL_FILE.FOPEN(var_filepath,'new_'||var_filename,'W',var_maxnum);
loop
 var_i:=var_i+1;
    UTL_FILE.GET_LINE(var_in_file,var_in_str);
 if substr(var_in_str,1,21) = '<a:DataType>VARCHAR2(' then
      var_j:=var_i;
      var_len := substr(var_in_str,22,instr(var_in_str,')',22,1) - 22);
      var_out_str:='<a:DataType>VARCHAR2('||to_char(ceil(to_number(var_len)*1.5))||')</a:DataType>';
   UTL_FILE.PUT_LINE(var_out_file,var_out_str);
 elsif var_i=var_j+1 and substr(var_in_str,1,10) = '<a:Length>' then
      var_len := substr(var_in_str,11,instr(var_in_str,')',11,1) - 11);
var_out_str:='<a:Length>'||to_char(ceil(to_number(var_len)*1.5))||'</a:Length>';
UTL_FILE.PUT_LINE(var_out_file,var_out_str);
 else 
 var_out_str:=var_in_str;
 UTL_FILE.PUT_LINE(var_out_file,var_out_str);
 end if;
end loop;
EXCEPTION
WHEN NO_DATA_FOUND THEN
begin
  UTL_FILE.FCLOSE(var_in_file);
  UTL_FILE.FCLOSE(var_out_file);
  end;
  when others then
  begin
    dbms_output.put_line(sqlerrm||':'||var_in_str);
    UTL_FILE.FCLOSE(var_in_file);
 UTL_FILE.FCLOSE(var_out_file);
  end;
END up_modify_pdm;

2)针对数据库中已经创建表对象的长度修改:up_modify_col_length

create or replace procedure up_modify_col_length
is
var_tab varchar2(30);
var_len number(10);
var_sql varchar2(2000) :=' ';
i number(10);
begin
  dbms_output.enable(50000);
  declare type tab_col is record(tab_name varchar2(30),col_name varchar2(30),data_len number(10));
  type type_array is table of tab_col index by binary_integer;
  var_array type_array;
  
  begin
    select col.TABLE_NAME,col.COLUMN_NAME,col.DATA_LENGTH bulk collect into var_array
    from USER_TAB_COLUMNS col,USER_TABLES  tab 
    where col.TABLE_NAME=tab.TABLE_NAME and col.DATA_TYPE='VARCHAR2' order by col.TABLE_NAME;
    
    var_tab := var_array(1).tab_name;
    var_len := Ceil(var_array(1).data_len*1.5);
    
    if var_len<=4000 then
      var_sql := 'alter table '||var_tab||' modify ('||var_array(1).col_name||' VARCHAR2('||to_char(var_len)||')';
    else
      dbms_output.put_line(var_tab||'.'||var_array(1).col_name||' length*1.5='||to_char(var_len)||' will be  more than 4000');
    end if;
    for i in 2..var_array.count loop
      begin
        if var_array(i).tab_name != var_tab then
          if var_sql != ' ' then
            var_sql := var_sql||')';
            var_sql := ltrim(var_sql);
            if substr(var_sql,1,1) = ',' then
              var_sql := substr(var_sql,2);
              var_sql := 'alter table '||var_tab||' modify ('|| var_sql;
            end if;
            begin
              execute immediate var_sql;
              exception
              when others then
                begin
                  dbms_output.put_line(sqlerrm||':'||var_sql);
                  return;
                end;
            end;
          end if;
          var_sql := ' ';
        end if;
        var_len := Ceil(var_array(i).data_len*1.5);
        if var_len > 4000 then
           dbms_output.put_line(var_array(i).tab_name||'.'||var_array(i).col_name||' length*1.5='||to_char(var_len)||' will be  more than 4000');
        else
          if var_array(i).tab_name != var_tab then
            var_sql := 'alter table '||var_array(i).tab_name||' modify ('||var_array(i).col_name||' VARCHAR2('||to_char(var_len)||')';
          else
            var_sql := var_sql||','||var_array(i).col_name||' VARCHAR2('||to_char(var_len)||')';
          end if;
        end if;          
        --dbms_output.put_line(var_array(i).tab_name||','||var_array(i).col_name||','||to_char(var_array(i).data_len));
        var_tab := var_array(i).tab_name;
      end;
    end loop;
     if var_sql != ' ' then
       var_sql := var_sql||')';
       var_sql := ltrim(var_sql);
       if substr(var_sql,1,1) = ',' then
         var_sql := substr(var_sql,2);
         var_sql := 'alter table '||var_tab||' modify ('|| var_sql;
       end if;
       begin
         execute immediate var_sql;
         exception
         when others then
           begin
             dbms_output.put_line(sqlerrm||':'||var_sql);
             return;
           end;
       end;
     end if;
  end; 
end up_modify_col_length;

     

原创粉丝点击