繁体   English   中英

从Sql Server中选择表并将数据插入到Mysql表中

[英]Select table from Sql server and insert data to Mysql table

我有一个正在运行的ms sql服务器,希望将一些数据复制到mysql数据库。

我已经可以连接到他们两个,所以我做了类似的事情:

$pdo = new PDO('SQLSERVER', $user, $password);
$sql = "SELECT id, name FROM users";
$stmt = $pdo->prepare($sql);
$stmt->execute();

$json_users = array();
while ($row = $stmt->fetchObject()){
   $json_users[] = $row;
}

$pdo = new PDO('MYSQLDB', $user, $password);

foreach ($json_users as $key => $value){
    $sql = "INSERT INTO users (id, name) VALUES (:id, :name)"
    $stmt = $pdo->prepare($sql);
    $stmt->bindParam('id', $value->id, PDO::PARAM_INT);
    $stmt->bindParam('name', $value->name, PDO::PARAM_STR);
    $stmt->execute();
}

这确实有效,但要花费大量时间才能使其大表化。

所以我的问题是我可以只通过一个插入查询就立即将sqlserver的完整结果插入mysql吗? 没有foreach?

更新:该表包含173398行和10列

对于准备好的语句(尤其是对于多插入),您希望将准备好的语句置于循环之外 您只需要设置一次查询,然后在每个后续调用中提供数据

$sql = "INSERT INTO users (id, name) VALUES (:id, :name)";
$stmt = $pdo->prepare($sql);
foreach($json_users as $key => $value){
    $stmt->bindParam('id', $value->id, PDO::PARAM_INT);
    $stmt->bindParam('name', $value->name, PDO::PARAM_STR);
    $stmt->execute();
}

您可以先将其从MSSQL导出到CSV文件,然后再将该文件导入MySQL。

$pdo = new PDO('SQLSERVER', $user, $password);
$sql = "SELECT id, name FROM users";
$stmt = $pdo->prepare($sql);
$stmt->execute();

$fp = fopen('/tmp/mssql.export.csv', 'w');
while ($row = $stmt->fetch(PDO::FETCH_NUM)){
   fputcsv($fp, array_values($row));
}
fclose($fp);
$pdo = new PDO('MYSQLDB', $user, $password, array(PDO::MYSQL_ATTR_LOCAL_INFILE => 1));

$sql = <<<eof
    LOAD DATA LOCAL INFILE '/tmp/mssql.export.csv'
     INTO TABLE user_copy
     FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
     LINES TERMINATED BY '\n'
    (id,name)
eof;
$pdo->exec($sql);

上面的一个缺点是,您需要在my.cnf中启用此配置(MySQL配置)

    [server]
    local-infile=1

由于MySQL无法读取他人拥有的文件,除非它以--local-infile = 1打开

我建议不要绑定值,而是生成查询字符串:

$sql = "";
foreach ($json_users as $key => $value){
    if ($sql=="") {
       $sql = "INSERT INTO users (id, name) VALUES ";
       $sql =." (".$value->id.',"'.$value->name.'")';
    } else {
       $sql .= ", (".$value->id.',"'.$value->name.'")';
    }
}

$stmt = $pdo->prepare($sql);
$stmt->execute();

这不是最佳实践,但是由于您信任数据源,因此可以提供帮助。

考虑批量插入而不是一次插入一行。

$sourcedb = new \PDO('SQLSERVER', $sourceUser, $sourcePassword);
$targetdb = new \PDO('MYSQLDB', $targetUser, $targetPassword);

$sourceCountSql = "SELECT count(*) count FROM users;";

/**
 * for mssql server 2005+ 
 */
$sourceSelectSql = "
SELECT
    id,
    name
FROM
    (
        SELECT
            ROW_NUMBER() OVER (ORDER BY id) RowNum,
            id,
            name
        FROM
            users
    ) users
WHERE
    RowNum >= %d
    AND RowNum < %d
ORDER BY
    RowNum
";

/**
 * for mssql server 2012+ 
 */
$sourceSelectSql = "
SELECT 
    FROM TableName ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
SELECT
    id,
    name
FROM
    users
ORDER BY
    id
OFFSET %d ROWS
FETCH NEXT %d ROWS ONLY        
";    

$sourceCount = $sourcedb->query($sourceCountSql, \PDO::FETCH_COLUMN, 0);

$rowCount = 1000;

$count = 0;
$count2 = 0;

for($x = 0; $x < $sourceCount; $x += $rowCount) {

    $sourceRecords = $sourcedb->query(sprintf($sourceSelectSql, $x, $rowCount), \PDO::FETCH_ASSOC);

    $inserts = [];

    foreach($sourceRecords as $row) {
        $inserts[] = sprintf("(:id_%1$d, :name_%1$d)", $count++);
    }

    $stmt = $targetdb->prepare(sprintf("INSERT INTO users (id, name) VALUES %s;", implode(',', $inserts));

    foreach($sourceRecords as $row) {
        $stmt->bindParam(sprintf('id_%d', $count2), $row['id'], \PDO::PARAM_INT);
        $stmt->bindParam(sprintf('name_%d', $count2), $row['name'], \PDO::PARAM_STR);
        $count2++;
    }

    $targetdb->execute();

    unset($inserts);

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM