当前位置:Gxlcms > 数据库问题 > MYSQL数据库迁移到POSTGRESQL数据库(人工迁移)

MYSQL数据库迁移到POSTGRESQL数据库(人工迁移)

时间:2021-07-01 10:21:17 帮助过:22人阅读


  • 将所有的INDEX语句单独生成一个文件(此步也可以省略,后面有其它方法)
    cat table_new.sql | egrep ‘\-|^\s*KEY|^\s*UNIQUE‘ > key.sql

  • 将所有的外键语句单独生成一个文件 (此步可以省略,后面有其它方法)
    cat table_new.sql | egrep ‘\-|^\s*CONSTRAINT‘ > constraint.sql

  • 去掉KEY和CONSTRAINT的语句,并生成新文件 table_last.sql

    cat table_new.sql | sed  ‘s/^\s*KEY.*$//‘ | sed ‘s/^\s*CONSTRAINT.*$//‘ | sed ‘s/^\s*UNIQUE.*$//‘  | sed ‘/^$/d‘> table_last.sql

  • 转换换行符

    unix2dos table_last.sql

  • 把文件COPY到WINDOWS中,用记事本工具(或其它工具)对一些特殊值进行查找、替换操作(此步的意思就是把mysql中的类型对应到postgresql中的类型),比如:

    查找 ID int(12) NOT NULL AUTO_INCREMENT 替换 ID bigserial NOT NULL (自增长类型字段)

    查找 datetime 替换 timestamp

    ……

  • 重新整理一些特殊表,因为第5步中去掉了所有KEY和CONSTRAINT的语句,所以如果表字段中包括KEY开头或是CONSTRAINT开头的字段时(比如字段 KEYCD,KEYTTL等)要把这些特殊的表的建表语句手工制作一变,并在table_last.sql中替换掉原来的语句。

  • 在Postgresql中执行table_last.sql语句(方法略),如果有错误进行微调,直到所有表建立成功。

  • 导入数据(先在mysql中导出,导出后的文件要替换换行符不然报错,然后再导入到postgresql)

    1. 导出语句(在MYSQL中执行以下语句,并复制结果后再次执行,便会在服务器的目录下生成以每个表为单位的数据文件,我用的工具是Navicat for Mysql。注意替换table_schema,这里生成数据文件的目录为:/usr/local/mysql/outfile/,也可换成其它目录)

    2. SELECT CONCAT(‘select * from ‘,
      table_name,
      " into outfile ‘/usr/local/mysql/outfile/",
      table_name ,
      ‘.dat‘ ,"‘"
      " fields terminated by ‘|‘ ;")
      FROM information_schema.tables
      WHERE table_schema=‘DEVELOP‘;
    3. 替换换行符后将生成的文件COPY到postgresql服务器的目录下
      sed -i ‘s/\r//g‘ outfile/*

    4. 导入语句(在postgresql中执行,得到查询结果后复制查询结果,并再次执行,注意一定要用有superuser权限的用户执行,这里用的是pgadmin工具,目录是/tmp/data,注意替换table_catalog中的值,我的数据名为DEVELOP)


    5. select ‘copy necsl.‘||table_name|| ‘ from ‘ || chr(39)||‘/tmp/data/‘
      ||upper(table_name)||
      ‘.dat‘ || chr(39) ||
      ‘ with DELIMITER ‘ || chr(39) || ‘|‘ || chr(39) ||‘;‘ 
      from information_schema.tables
      where table_schema=‘necsl‘ and
      table_catalog=‘DEVELOP‘ ;
  • 数据导入后可以用以下方法验证是否导入正确


  • --在mysql及PG中分别建立下表
    create table table_count(tblname varchar(100) primary key not null,tblrecorder integer);
  • /*在mysql中执行以下语句,并将结果复制后再次执行,将会生成在表table_count中生成每张表有多少记录*/
    SELECT CONCAT(‘insert into table_count select ‘ ,"‘",table_name,"‘",‘ ,count(*) from ‘,
    table_name ,";")
    FROM information_schema.tables
    WHERE table_schema=‘DEVELOP‘;
    
    
    --在postgresql中执行以下语句,并将结果复制后再次执行,将会生成在表table_count中生成每张表有多少记录,然后与mysql中table_count的表比较即可
    select ‘insert into necsl.table_count select ‘|| quote_literal(table_name) ||‘,count(*) from   necsl.‘||table_name|| ‘;‘  
    from information_schema.tables
    where table_schema=‘necsl‘ and
    table_catalog=‘DEVELOP‘ ;
  • --如果导入有问题,可以在PG中执行以下句语生成清空所有表的语句,将执行结果复制再执行即可清空所有表
    PG truncate
    select ‘truncate table  necsl.‘||table_name|| ‘;‘  
    from information_schema.tables
    where table_schema=‘necsl‘ and
    table_catalog=‘DEVELOP‘ ;
  • /*生成索引信息及外键,在mysql中分别执行以下语句,并将结果复制到POSTGRESQL中执行*/
    /*生成唯一索引*/
    select 
       CONCAT (
         ‘CREATE UNIQUE INDEX ‘ ,          
          table_name,‘_IDX_‘,index_name,
         ‘ ON ‘,
          table_name,
         ‘(‘,
          GROUP_CONCAT(column_name order by seq_in_index),
          ‘);‘
    )
    from statistics
    where table_schema=‘DEVELOP‘
    AND INDEX_NAME <>‘PRIMARY‘
    AND INDEX_SCHEMA=‘DEVELOP‘
    AND NON_UNIQUE=0
    GROUP BY index_name,table_name
    ORDER BY TABLE_NAME,INDEX_NAME,seq_in_index asc
    
    
    /*生成btree索引*/
    select 
       CONCAT (
         ‘CREATE INDEX ‘ ,          
          table_name,‘_IDX_‘,index_name,
         ‘ ON ‘,
          table_name,
         ‘(‘,
          GROUP_CONCAT(column_name order by seq_in_index),
          ‘);‘
    )
    from statistics
    where table_schema=‘DEVELOP‘
    AND INDEX_NAME <>‘PRIMARY‘
    AND INDEX_SCHEMA=‘DEVELOP‘
    AND NON_UNIQUE=1
    GROUP BY index_name,table_name
    ORDER BY TABLE_NAME,INDEX_NAME,seq_in_index asc
    
    /*生成外键 */
    select
    concat(‘alter table ‘,
    c.TABLE_NAME,
    ‘ add constraint ‘,
    c.CONSTRAINT_NAME,
    ‘ foreign key(‘,
    c.COLUMN_NAME,
    ‘) references ‘,
    c.REFERENCED_TABLE_NAME,
    ‘( ‘,
    c.REFERENCED_COLUMN_NAME,
    ‘);‘)
    from TABLE_CONSTRAINTS t,KEY_COLUMN_USAGE c
    where t.CONSTRAINT_SCHEMA=‘DEVELOP‘
    AND t.CONSTRAINT_TYPE=‘FOREIGN KEY‘
    AND t.TABLE_SCHEMA=‘DEVELOP‘
    AND c.REFERENCED_TABLE_SCHEMA=‘DEVELOP‘
    AND t.CONSTRAINT_NAME =c.CONSTRAINT_NAME
    and t.table_name=c.table_name;
  • 17.生成以上信息后,在PG中建立以下函数,用于重置所有的sequence(如果没有自增长类型可忽略此步),建立放在public模式下

    CREATE OR REPLACE FUNCTION pro_resetallseq()
      RETURNS void AS
    $BODY$
     DECLARE
               tmp VARCHAR(512);
               maxval bigint;
               stmt  record;
     BEGIN
           FOR stmt IN   select sequence_name,REPLACE(sequence_name,‘_id_seq‘,‘‘) as tnm from information_schema.sequences where 
    
    sequence_catalog=‘DEVELOP‘ and sequence_schema=‘necsl‘  LOOP
                      
    		  tmp := ‘SELECT MAX(ID) FROM ‘|| quote_ident(stmt.tnm) || ‘;‘;
    		  EXECUTE tmp into maxval;
                      if not (maxval  is NULL or maxval = 0) then                    
                         EXECUTE ‘SELECT SETVAL(‘|| quote_literal(stmt.sequence_name) || ‘,‘ || maxval || ‘);‘;
                      end if;                  
                      
           END LOOP;
           RAISE NOTICE ‘finished .....‘;
           END;
    $BODY$
      LANGUAGE plpgsql

    18.建立成功后可以用以下语句重置所有的sequence

    select pro_resetallseq();

    19.关于mysql中的函数(存储过程)因为语法差别较大,只能在PG中重写。我没有找到太好的方法。


    因为时间紧,所以没有写工具,过程也比较粗糙,仅供参考,如果有好的建议欢迎留言,谢谢阅读。

    本文出自 “镜子” 博客,请务必保留此出处http://383133430.blog.51cto.com/454215/1686169

    MYSQL数据库迁移到POSTGRESQL数据库(人工迁移)

    标签:数据库   mysql   迁移   数据   postgresql   

    人气教程排行