轻量级的解决Oracle表转Mysql表之间结构转换

问题背景       

     最近在做Oracle和Mysql之间的库表迁移,度娘了很多资料,大部分都是基于powerdesigner 或者Navicat等重量级的工具,鉴于各种限制原因,不能使用工具来实现数据库迁移。数据库迁移拆分成建表语句、数据迁移、存储过程、视图等部分。苦于手撕建表语句,寻找一种快速转换表结构的方式尤为重要,本文章可用于解决建表语句部分。

解决思路

     总结归纳了Oracle和Mysql的语法区别,以及目前表结构中使用到数据类型如下:

OracleMysql
VARCHAR2VARCHAR
NUMBER

DECIMAL

INTEGERINT
CHARCHAR

通过自定义oracle函数的方式,在方法体中对数据类型进行转换,去生成具体表的DDL语句(Mysql语法)。

具体的代码块


CREATE OR REPLACE FUNCTION F_LIMS_GET_SQL_FOR_MYSQL(PI_TABLENAME IN VARCHAR2,
                                                    PI_ISDROP    IN INTEGER := 1)
  RETURN CLOB IS
  FunctionResult clob;
  V_TABLENAME         VARCHAR(100);
  V_RET_SQL           VARCHAR2(4000);
  V_SQL_HEADER        VARCHAR2(1000);
  V_SQL_BODY          CLOB;
  V_SQL_INDEX         VARCHAR2(4000);
  V_SQL_TABLE_COMMENT VARCHAR(400);
  V_SQL_PK_COL_LIST   VARCHAR(1000);
  -- 根据当前数据库和表名,生成mysql建表语句
BEGIN
  -- 表名统一为大写
  SELECT UPPER(PI_TABLENAME) INTO V_TABLENAME FROM DUAL;

  SELECT MAX(T.COMMENTS)
    INTO V_SQL_TABLE_COMMENT
    FROM USER_TAB_COMMENTS T
   WHERE T.TABLE_NAME = V_TABLENAME;

  SELECT MAX(LISTAGG('`' || A.COLUMN_NAME || '` '))
    INTO V_SQL_PK_COL_LIST
    FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
   WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
     AND B.CONSTRAINT_TYPE = 'P'
     AND A.TABLE_NAME = V_TABLENAME
   GROUP BY A.TABLE_NAME;

  V_SQL_HEADER := '-- ' || V_SQL_TABLE_COMMENT || ' 建表语句' || CHR(13);

  IF PI_ISDROP = 1 THEN
    V_SQL_HEADER := V_SQL_HEADER || 'DROP TABLE IF EXISTS `' || V_TABLENAME || '`;' ||
                    CHR(13);
  END IF;
  V_SQL_HEADER := V_SQL_HEADER || 'CREATE TABLE `' || V_TABLENAME || '`  (';

  -- 表列信息
  SELECT LISTAGG(CHR(13) || '`' || T.COLUMN_NAME || '` ' ||
                   (CASE
                      WHEN T.DATA_TYPE = 'VARCHAR2' OR T.DATA_TYPE = 'NVARCHAR2' THEN
                       'VARCHAR(' || T.DATA_LENGTH || ')'
                      WHEN T.DATA_TYPE = 'DATE' THEN
                       'DATETIME'
                      WHEN T.DATA_TYPE = 'CLOB' THEN
                       'MEDIUMTEXT'
                      WHEN T.DATA_TYPE = 'NUMBER' AND NVL(T.DATA_SCALE,0) = 0 THEN
                       'INT'
                      WHEN T.DATA_TYPE = 'NUMBER' AND NVL(T.DATA_SCALE,0) != 0 THEN
                       'DECIMAL(' || T.DATA_PRECISION || ',' || T.DATA_SCALE || ')'
                      WHEN T.COLUMN_NAME = 'ID' THEN
                       'VARCHAR(32)'
                      ELSE
                       T.DATA_TYPE
                    END) || DECODE(T.NULLABLE, 'N', ' NOT NULL ', '') ||
                   ' COMMENT ''' || TC.COMMENTS || ''',')
                   WITHIN GROUP (ORDER BY T.COLUMN_ID)
    INTO V_SQL_BODY
    FROM USER_TAB_COLUMNS T
    LEFT JOIN USER_COL_COMMENTS TC
      ON T.TABLE_NAME = TC.TABLE_NAME
     AND T.COLUMN_NAME = TC.COLUMN_NAME
   WHERE T.TABLE_NAME = V_TABLENAME
   ORDER BY T.COLUMN_ID;

  IF V_SQL_PK_COL_LIST IS NOT NULL THEN
    V_SQL_BODY := V_SQL_BODY || ' ,' || CHR(13) || ' PRIMARY KEY (' ||
                  V_SQL_PK_COL_LIST || ')  ';
  END IF;

  -- 表备注
  V_SQL_BODY := V_SQL_BODY || CHR(13) || ') COMMENT = ''' ||
                V_SQL_TABLE_COMMENT || ''';' || CHR(13);

  -- 唯一索引 
  SELECT (LISTAGG('@ALTER TABLE `' || A.TABLE_NAME ||
                    '` ADD UNIQUE INDEX (' ||
                    LISTAGG('`' || A.COLUMN_NAME || '`') || ');@'))
    INTO V_SQL_INDEX
    FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
   WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
     AND B.CONSTRAINT_TYPE = 'U'
     AND A.TABLE_NAME = V_TABLENAME
   GROUP BY A.TABLE_NAME, A.CONSTRAINT_NAME;

  IF V_SQL_INDEX IS NOT NULL THEN
    V_SQL_INDEX := REPLACE(REPLACE(V_SQL_INDEX, '@,@', CHR(13)), '@', '');
    V_SQL_INDEX := '-- 创建索引' || CHR(13) || V_SQL_INDEX;
  END IF;

  RETURN V_SQL_HEADER || V_SQL_BODY || V_SQL_INDEX;
  RETURN (FunctionResult);
END F_LIMS_GET_SQL_FOR_MYSQL;

执行方法 

SELECT F_LIMS_GET_SQL_FOR_MYSQL('TABLENAME',0) FROM DUAL

参考资料

Oracle数据库表结构转MySQL表结构_oracle表结构怎么手动mysql表结构教程-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值