INSERT INTO table (field1,field2,field3) VALUES ('value','value','value'),('value','value');
通常在MysqL中这个查询是直接的,并且会插入3行,如何在MysqLi中执行此操作而不使用预准备语句或者可能使用预准备语句但不会太复杂?我只是想知道是否有办法执行这样的查询而不用在PHP中做额外的时髦的东西.
本质上,我有一些提取的数据,每个插入大约有10行(除了有多行之外还需要多个插入),这就是我需要的.我只希望用查询来执行此操作,因为我通常使用MysqL完成它,而不是每行添加多个插入.
以下示例假设您未指定的“提取数据”存储在数组数组中:$bigArray [0 … datasetsize] [0 … 2].
方法1 – 旧学校
您可以像以前一样直接进行操作,只需构建查询字符串并使用它查询数据库即可.如您所指定,插入一次捆绑10个.下面的代码显示了一个这样的bundle,并且可以简单地扩展到整个数据集(bigArray).应该使用MysqLi :: escape_string对数据进行转义(此处未完成).
在所有示例中,假设要插入的数据是整数.
$sql = "INSERT INTO testTable (fieldA,fieldB,fieldC) VALUES ";
for ($i = 0; $i < 10; ++$i)
{
if ($i > 0) $sql .= ",";
$sql .= "({$bigArray[$i][0]}),({$bigArray[$i][1]}),({$bigArray[$i][2]})";
}
$db->query($sql);
方法2 – 尽可能简单
如果要使用预准备语句和参数绑定,则第一项工作可能如下所示.虽然不是最佳,但声明只准备一次.但是,每个插入的变量都是绑定的,这很浪费(但很简单).由于插入没有捆绑,因此示例循环超过10.
$statement = $db->prepare("INSERT INTO testTable (fieldA,fieldC) VALUES (?,?,?)");
for ($i = 0; $i < 10; ++$i)
{
$statement->bind_param("iii",$bigArray[$i][0],$bigArray[$i][1],$bigArray[$i][2]);
$statement->execute();
}
方法3 – 优化
准备好的语句和多个插入组合使得性能几乎与方法1的原始插入查询相同.实际结果将根据您的设置而有所不同,但是对我的系统进行快速测试,同时使用本地和远程数据库显示性能有几个百分比使用优化方法更快地点,如果需要转义方法1中的数据,则增加几点.
以下使用call_user_func_array,但如果您知道每次要捆绑多少插入并直接构建调用bind_param,则可以避免这种情况.这将进一步提高性能.
为清楚起见,这个例子包括外环并假定要插入总共10k行(即bigArray [0..9999] [0..2]).
$sql = "INSERT INTO testTable (fieldA,?)".str_repeat(",(?,?)",9);
$statement = $db->prepare($sql);
// This is the type string used by statement::bind_param.
// Example assumes all INTs.
$types = (array)str_repeat("i",30);
$values = array_fill(0,30,0); // A bit of unneeded variable init.
// * See notes following code snippet on why the intermediate array is used.
$intermediate = array();
for ($n = 0; $n < 30; ++$n)
{
$intermediate[$n] = &$values[$n];
}
call_user_func_array(array(&$statement,"bind_param"),array_merge($types,$f));
for ($j = 0; $j < 1000; ++$j)
{
for ($i = 0; $i < 10; ++$i)
{
$values[$i*3] = $bigArray[$i][0];
$values[$i*3+1] = $bigArray[$i][1];
$values[$i*3+2] = $bigArray[$i][2];
}
$statement->execute();
}
// call_user_func_array with bind_param requires the values be
// passed by reference which is evaluated only on the initial
// call. Using $values[...] = &$bigArray[...] below won't work
// and an intermediate array referencing $values is used. This
// bit of "extra funky stuff" can be avoided at a very slight
// performance penalty by setting $values[...] = $bigArray[...]
// AND EVALUATING EACH TIME (move call_user_func_array
// inside the outer loop,i.e. right above $statement->execute()).