【问题标题】:perl script to connect two databases at same timeperl 脚本同时连接两个数据库
【发布时间】:2016-05-06 22:48:32
【问题描述】:

我正在尝试从 1 个 Perl 脚本连接到同一 MySQL 实例上的 2 个数据库。

我在迁移脚本中使用它,我从原始数据库中获取数据并将其插入到新数据库中。

连接到 1 个数据库然后尝试与同一用户启动第二个连接只会将当前数据库更改为新数据库。

#!/usr/bin/perl

use DBI;
use strict;

my $driver = "mysql";
my $database1 = "db1";
my $dsn1 = "DBI:$driver:database=$database1";
my $userid = "userhead";
my $password = "pwdhead";
my $database2 = "db2";
my $dsn2 = "DBI:$driver:database=$database2";

my $dbh1 = DBI->connect($dsn1, $userid, $password ) or die $DBI::errstr;
my $dbh2 = DBI->connect($dsn2, $userid, $password ) or die $DBI::errstr;

my $sth = $dbh2->prepare("INSERT INTO Persons") $dbh1->prepare("SELECT *FROM Persons");
$sth->execute() or die $DBI::errstr;
print "Number of rows found :" + $sth->rows;

在上面的示例中,我试图从一个数据库表复制到另一个数据库表。但我在运行脚本时遇到错误。请帮帮我

【问题讨论】:

标签: mysql database perl


【解决方案1】:

您猜测,您正在尝试使用相同的数据库句柄来连接到两个数据库。如果你需要操作两个独立的连接那么你需要两个独立的句柄

该程序使用data_sources 类方法来发现所有可用的MySQL 数据库并创建到每个数据库的连接,将句柄放在数组@dbh 中。例如,您可以正常使用该数组的每个元素

my $stmt = $dbh[0]->prepare('SELECT * FROM table)

您可能更喜欢手动设置@databases 数组,或者两个数据源的用户名和密码可能不同,因此可能需要对此进行一些更改

use strict;
use warnings 'all';

use DBI;

my $user = 'username';
my $pass = 'password';

my @databases = DBI->data_sources('mysql');

my @dbh = map { DBI->connect($_, $user, $pass) } @databases;


更新

您需要从源表中选择数据,一次获取一行,然后将每一行插入到目标表中

这是一个如何工作的想法,但您需要调整 INSERT 语句的 VALUES 中的问号数以匹配列数

请注意,如果您只是想复制整个数据集,有更好的方法来解决这个问题。特别是,如果您有任何外键约束,那么您将无法添加数据,直到它所依赖的表被填充

#!/usr/bin/perl

use strict;
use warnings 'all';

use DBI;

my $userid   = "userhead";
my $password = "pwdhead";

my ($dbase1, $dbase2) = qw/ db1 db2 /;

my $dsn1 = "DBI:mysql:database=$dbase1";
my $dsn2 = "DBI:mysql:database=$dbase2";

my $dbh1 = DBI->connect($dsn1, $userid, $password ) or die $DBI::errstr;
my $dbh2 = DBI->connect($dsn2, $userid, $password ) or die $DBI::errstr;

my $select = $dbh1->prepare("SELECT * FROM Persons");
my $insert = $dbh2->prepare("INSERT INTO Persons VALUES (?, ?, ?, ?, ?)");

$select->execute;
while ( my @row = $select->fetchrow_array ) {
    $insert->execute(@row);
}

如果您需要单独处理源数据中的列,则可以使用命名标量而不是数组@row。像这样

while ( my ($id, $name) = $select->fetchrow_array ) {
    my $lastname = '';
    $insert->execute($id, $name, $lastname);
}

【讨论】:

  • 请检查已编辑的问题。我正在尝试将数据从一个数据库表复制到另一个数据库表。但我不知道如何加入 perl 脚本中的语句
  • @ashu:好的,我已经为我的解决方案添加了更新。您不能“加入 Perl 脚本中的语句”——您只需从一个表中读取数据,然后将其插入到另一个表中
  • @ashu:我不能告诉你如何为lastname 列生成数据,但是数组@row 包含来自db1 的所有列的值。您可以使用命名的标量变量而不是我在解决方案中显示的数组
【解决方案2】:

A 计划(尤其是一次性任务):

在源机器上运行mysqldump;将输出提供给目标机器上的mysql。这将更快更简单。如果您使用的是 Unix 机器,请使用来自 Perl 的 exec()(如果您愿意)。

B 计划(尤其是重复任务):

如果表不是“太大”,请使用SELECT 将所有行提取到 Perl 中的数组中。然后INSERT 将行写入目标机器。如果您构建多行 INSERT 或创建 CSV 文件并使用 LOAD DATA 而不是 INSERT,则可以加快(通过一些努力)。

【讨论】:

    猜你喜欢
    • 2015-11-27
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多