我试图切换一些硬编码的查询以使用参数化输入,但是遇到一个问题:如何格式化参数化批量插入的输入?
当前,代码如下所示:
$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);
一个可能的解决方案(从如何将数组插入到一个带有PHP和PDO的单个MySQL Prepared语句中修改而来)似乎是:
$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); }
有没有更好的方法来完成带有参数化查询的批量插入?
好吧,您有三个选择。
一次构建-执行多次。基本上,您只需为一行准备一次插入,然后循环执行该插入。由于SQLSERVER扩展在准备好查询后不支持重新绑定查询(您需要使用reference进行肮脏的破解),所以这可能不是最佳选择。
一次构建-一次执行。基本上,您按照示例中的说明构建了一个巨型插入物,将其绑定一次,然后执行它。这有点脏,并且错过了准备查询所提供的一些好处。但是,由于需要选项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); }
两种方法都足够。做您认为最适合您要求的事情…