[英]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.