DDL(概ね)変換スクリプト(PostgreSQL→SQLServer)


需要はほぼないと思いますが、PostgreSQLのDDLをSQLServer用のDDLに変換する必要が発生した時にめんどうだったので作成したスクリプトです。

注意:完璧な変換ではありません。

#!/usr/bin/perl
#
# Convert dumped PostgreSQL ddl to MS SQLServer ddl.
#

use strict;
use warnings;

use File::Basename;

my $targetFile = shift @ARGV;

my @converted;

open SRCDDL, "<:encoding(utf-8)", './'.$targetFile or die "[Error] Failed to open input file";
    my $row = 0;
    while (my $line = <SRCDDL>) {
       $row++;

       $line =~ s/\r//g;
       $line =~ s/\n//g;

       #
       # Type of Strings
       #

       if ($line =~ /varchar|character varying/i) {
           $line =~ s/varchar|character varying/nvarchar/gi;
           print "[$row]:Convert varchar to nvarchar.\n";
       }

       if ($line =~ /character|char/i) {
           # Nothing TODO.
       }

       if ($line =~ /\s{1}text/i) {
           $line =~ s/\s{1}text/ nvarchar(max) /gi;
           print "[$row]:Convert text to nvarchar(max).\n";
       }

       #
       # Type of numerics
       #

       if ($line =~ /\s{1}int2|smallint/i) {
           $line =~ s/\s{1}int2/ smallint/gi;
           print "[$row]:Convert int2 to smallint.\n";
       }

       if ($line =~ /\s{1}int4|integer/i) {
           $line =~ s/\s{1}int4| integer/ int/gi;
           print "[$row]:Convert int4|integer to int.\n";
       }

       if ($line =~ /\s{1}int8|bigint/i) {
           $line =~ s/\s{1}int8/ bigint/gi;
           print "[$row]:Convert int8 to bigint.\n";
       }

       #
       # Type of serials
       #

       if ($line =~ /smallserial|\s{1}serial2/i) {
           $line =~ s/smallserial|\s{1}serial2/ smallint/gi;
           print "[$row]:Convert smallserial|serial2 to smallint.\n";
       }

       if ($line =~ /bigserial|\s{1}serial8/i) {
           $line =~ s/bigserial|\s{1}serial8/ bigint/gi;
           print "[$row]:Convert bigserial|serial8 to bigint.\n";
       }

       if ($line =~ /\s{1}(serial)[\s|,]/i) {
           $line =~ s/\s{1}(serial)([\s|,])/ int$2/gi;
           print "[$row]:Convert serial to int.\n";
       }

       #
       # Type of float
       #

       if ($line =~ /decimal|numeric/i) {
           # Nothing TODO.
       }

       if ($line =~ /float4/i) {
           $line =~ s/float4/real/gi;
           print "[$row]:Convert float4 to real.\n";
       }

       if ($line =~ /double precision|float8/i) {
           $line =~ s/double precision|float8/float\(25\)/gi;
           print "[$row]:Convert double precision|float8 to float(25).\n";
       }

       #
       # Type of dates
       #

       if ($line =~ /timestamp/i) {
           # remove time zone option
           $line =~ s/with time zone//gi;
           $line =~ s/without time zone//gi;

           $line =~ s/timestamp\(\d\)+/datetime2\(6\)/gi;
           $line =~ s/timestamp/datetime2\(6\)/gi;

           # change call function
           $line =~ s/now\(\)/getdate\(\)/gi;

           print "[$row]:Convert timestamp.\n";
       }

       #
       # Type others
       #

       if ($line =~ /boolean/i) {
           $line =~ s/true/1/gi;
           $line =~ s/false/0/gi;

           $line =~ s/boolean/bit/gi;

           print "[$row]:Convert boolean to bit.\n";
       }

       #
       # Convert "CONSTRAINT"
       #

       if ($line =~ /alter table only/i) {
           $line =~ s/only//gi;
           print "[$row]:Remove 'only' from ALTER TABLE.\n";
       }

       push(@{converted}, $line);

    }
close SRCDDL;

my $outFile = $targetFile . ".mssql";
open OUTPUT, ">:encoding(utf-8)", $outFile or die "[Error] False open output file ($outFile)";
    print OUTPUT join "\n", @{converted};
close OUTPUT;

使用方法

Convert元のPostgreSQLのDDLをDump

pg_dump -h localhost -d testdb -U testuser --schema-only --no-owner --file={path to}/ddl_postgres.dump

Dumpしたファイルを指定して実行

例:

$ perl convert_ddl.pl ddl_postgres_test.dump

ddl_postgres_test.dump.mssqlが生成される

備考

  • Serial型はIntegerに変換しています(INDENTITYに変換するなどはしていません)
  • その他、目的に応じてカスタマイズしてください