我正在尝试切换一些硬编码查询以使用参数化输入,但我遇到了一个问题:如何格式化参数化批量插入的输入?
目前,代码如下所示:
$data_insert = "INSERT INTO my_table (field1, field2, field3) ";
$multiple_inserts = false;
while ($my_condition)
{
if ($multiple_inserts)
{
$data_insert .= " UNION ALL ";
}
$data_insert .= " SELECT myvalue1, myvalue2, myvalue3 ";
}
$recordset = sqlsrv_query($my_connection, $data_insert);
可能的解决方案(从How to insert an array into a single MySQL Prepared statement w/ PHP and PDO修改)似乎是:
$sql = 'INSERT INTO my_table (field1, field2, field3) VALUES ';
$parameters = array();
$data = array();
while ($my_condition)
{
$parameters[] = '(?, ?, ?)';
$data[] = value1;
$data[] = value2;
$data[] = value3;
}
if (!empty($parameters))
{
$sql .= implode(', ', $parameters);
$stmt = sqlsrv_prepare($my_connection, $sql, $data);
sqlsrv_execute($stmt);
}
有没有更好的方法来完成带参数化查询的批量插入?
答案 0 :(得分:6)
嗯,你有三个选择。
构建一次 - 执行多次。基本上,您为一行准备插入一次,然后遍历执行它的行。由于SQLSERVER扩展在准备后不支持重新绑定查询(您需要执行dirty hacks with references),这可能不是最佳选择。
构建一次 - 执行一次。基本上,如您在示例中所述,构建一个巨型插入,绑定一次,然后执行它。这有点脏,并且错过了准备查询所带来的一些好处。但是,由于需要参考选项1的参考,我会这样做。我认为构建一个巨大的查询而不是依赖变量引用更清晰。
构建多个 - 执行多个。基本上,采取您正在进行的方法,并调整它以重新准备每隔这么多记录的查询。这可以防止过大的查询和“批量”查询。所以像这样:
$sql = 'INSERT INTO my_table (field1, field2, field3) VALUES ';
$parameters = array();
$data = array();
$execute = function($params, $data) use ($my_connection, $sql) {
$query = $sql . implode(', ', $parameters);
$stmt = sqlsrv_prepare($my_connection, $query, $data);
sqlsrv_execute($stmt);
}
while ($my_condition) {
$parameters[] = '(?, ?, ?)';
$data[] = value1;
$data[] = value2;
$data[] = value3;
if (count($parameters) % 25 == 0) {
//Flush every 25 records
$execute($parameters, $data);
$parameters = array();
$data = array();
}
}
if (!empty($parameters)) {
$execute($sql, $parameters, $data);
}
任何一种方法都足够了。做你认为最符合你要求的......
答案 1 :(得分:2)
为什么不使用“准备一次,执行多次”的方法。我知道你想要它全部失败或者全部工作,但是用事务来处理它并不是很难:
http://www.php.net/manual/en/pdo.begintransaction.php