Perl MSSQL 액세스 및 MySQL 데이터베이스 스크립트 인스턴스로 마이그레이션
using DBI;
my $cs = "DRIVER={FreeTDS};SERVER= ;PORT=1433;DATABASE= ;UID=sa;PWD= ;TDS_VERSION=7.1;charset=gb2312";
my $dbh = DBI->connect("dbi:ODBC:$cs") or die $@;
본인은 윈도우즈를 잘 사용하지 않기 때문에 QQ군 데이터베이스를 연구하기 위해 MSSQL에서 MySQL로 데이터를 옮겨야 합니다. 특히 QQ군 데이터베이스에 Windows Server 2008과 SQL Server 2008r2를 설치했습니다. 며칠 지나면 평가가 만료됩니다. MySQL을 연구한 Workbench는 MS SQL Server에서 데이터를 옮기는 능력이 있습니다. 그러나 QQ군과 같은 거대한 데이터와 라이브러리별 데이터는 너무 번거롭습니다.따라서 데이터베이스를 MSSQL에서 MySQL로 이동하는 데 사용되는 일반적인 퍼블릭 스크립트를 썼고 bash와 결합하여 이 20여 개의 라이브러리에서 100장의 테이블을 쉽게 옮겼다. 퍼블릭 코드는 다음과 같다.
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
die "Usage: qq db
" if @ARGV != 1;
my $db = $ARGV[0];
print "Connectin to databases $db...
";
my $cs = "DRIVER={FreeTDS};SERVER=MSSQL ;PORT=1433;DATABASE=$db;UID=sa;PWD=MSSQL ;TDS_VERSION=7.1;charset=gb2312";
sub db_connect
{
my $src = DBI->connect("dbi:ODBC:$cs") or die $@;
my $target = DBI->connect("dbi:mysql:host=MySQL ", "MySQL ", "MySQL ") or die $@;
return ($src, $target);
}
my ($src, $target) = db_connect;
print "Reading table schemas....
";
my $q_tables = $src->prepare("SELECT name FROM sysobjects WHERE xtype = 'U' AND name != 'dtproperties';");#
my $q_key_usage = $src->prepare("SELECT TABLE_NAME, COLUMN_NAME from INFORMATION_SCHEMA.KEY_COLUMN_USAGE;");#
$q_tables->execute;
my @tables = ();
my %keys = ();
push @tables, @_ while @_ = $q_tables->fetchrow_array;
$q_tables->finish;
$q_key_usage->execute();
$keys{$_[0]} = $_[1] while @_ = $q_key_usage->fetchrow_array;
$q_key_usage->finish;
#
my $q_index = $src->prepare(qq(
SELECT T.name, C.name
FROM sys.index_columns I
INNER JOIN sys.tables T ON T.object_id = I.object_id
INNER JOIN sys.columns C ON C.column_id = I.column_id AND I.object_id = C.object_id;
));
$q_index->execute;
my %table_indices = ();
while(my @row = $q_index->fetchrow_array)
{
my ($table, $column) = @row;
my $columns = $table_indices{$table};
$columns = $table_indices{$table} = [] if not $columns;
push @$columns, $column;
}
$q_index->finish;
# MySQL
$target->do("DROP DATABASE IF EXISTS `$db`;") or die "Cannot drop old database $db
";
$target->do("CREATE DATABASE `$db` DEFAULT CHARSET = utf8 COLLATE utf8_general_ci;") or die "Cannot create database $db
";
$target->disconnect;
$src->disconnect;
my $total_start = time;
for my $table(@tables)
{
my $pid = fork;
unless($pid)
{
($src, $target) = db_connect;
my $start = time;
$src->do("USE $db;");
# , MySQL DDL
my $q_schema = $src->prepare("SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = ? ORDER BY ORDINAL_POSITION;");
$target->do("USE `$db`;");
$target->do("SET NAMES utf8;");
my $key_column = $keys{$table};
my $ddl = "CREATE TABLE `$table` (
";
$q_schema->execute($table);
my @fields = ();
while(my @row = $q_schema->fetchrow_array)
{
my ($column, $nullable, $datatype, $length) = @row;
my $field = "`$column` $datatype";
$field .= "($length)" if $length;
$field .= " PRIMARY KEY" if $key_column eq $column;
push @fields, $field;
}
$ddl .= join(",
", @fields);
$ddl .= "
) ENGINE = MyISAM;
";
$target->do($ddl) or die "Cannot create table $table
";
#
my $indices = $table_indices{$table};
if($indices)
{
for(@$indices)
{
$target->do("CREATE INDEX `$_` ON `$table`(`$_`);
") or die "Cannot create index on $db.$table$.$_
";
}
}
#
my @placeholders = map {'?'} @fields;
my $insert_sql = "INSERT DELAYED INTO $table VALUES(" .(join ', ', @placeholders) . ");
";
my $insert = $target->prepare($insert_sql);
my $select = $src->prepare("SELECT * FROM $table;");
$select->execute;
$select->{'LongReadLen'} = 1000;
$select->{'LongTruncOk'} = 1;
$target->do("SET AUTOCOMMIT = 0;");
$target->do("START TRANSACTION;");
my $rows = 0;
while(my @row = $select->fetchrow_array)
{
$insert->execute(@row);
$rows++;
}
$target->do("COMMIT;");
# ,
my $elapsed = time - $start;
print "Child process $$ for table $db.$table done, $rows records, $elapsed seconds.
";
exit(0);
}
}
print "Waiting for child processes
";
#
while (wait() != -1) {}
my $total_elapsed = time - $total_start;
print "All tasks from $db finished, $total_elapsed seconds.
";
이 스크립트는 테이블마다 하위 프로세스와 해당하는 데이터베이스 연결을 보여 줍니다. 따라서 이 이전을 하기 전에 목표 MySQL 데이터베이스 설정의 최대 연결 수를 견딜 수 있도록 해야 합니다.그리고 bash에서 실행합니다.
for x in {1..11};do ./qq.pl QunInfo$x; done
for x in {1..11};do ./qq.pl GroupData$x; done
상관하지 마십시오. 스크립트는 MSSQL 이쪽 테이블 구조에 따라 MySQL 쪽에서 같은 구조를 만들고 색인을 설정합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.