下面是准备好的语句代码的片段:
for( $j = 0; $j < $abilitiesMax - 2; $j++ ){
$stmtAbility->bind_param('iiiii', $abilityArray[$i]["match_id"] , $abilityArray[$i]["player_slot"],
$abilityArray[$i][$j]["ability"], $abilityArray[$i][$j]["time"], $abilityArray[$i][$j]["level"] );
if( !($stmtAbility->execute()) ){
echo "<p>$db->error</p>";
echo "<p>ERROR: when trying to insert abilities query</p>";
}
}
它完成工作,但只有在数百次插入之后。是否有方法将列表或数组绑定到bind_param()参数,只需运行$stmtability->execute one time或其他可以提高性能的方法。
抱歉,如果这是问和回答之前。我四处看了一会儿,发现了一些类似的问题,但没有什么能明确地回答我的要求。
通过动态构造一个大容量insert语句查询来准备它是可能的,但是需要一些技巧。最重要的是使用str_pad()
构造可变长度的查询字符串,以及使用call_user_func_array()
调用具有可变数目参数的bind_param()
。
function insertBulkPrepared($db, $table, $fields, $types, $values) {
$chunklength = 500;
$fieldcount = count($fields);
$fieldnames = '`'.join('`, `', $fields).'`';
$prefix = "INSERT INTO `$table` ($fieldnames) VALUES ";
$params = '(' . str_pad('', 3*$fieldcount - 2, '?, ') . '), ';
$inserted = 0;
foreach (array_chunk($values, $fieldcount*$chunklength) as $group) {
$length = count($group);
if ($inserted != $length) {
if ($inserted) $stmt->close();
$records = $length / $fieldcount;
$query = $prefix . str_pad('', 3*$length + 2*($records - 1), $params);
#echo "\n<br>Preparing '" . $query . "'";
$stmt = $db->prepare($query);
if (!$stmt) return false;
$binding = str_pad('', $length, $types);
$inserted = $length;
}
array_unshift($group, $binding);
#echo "\n<br>Binding " . var_export($group, true);
$bound = call_user_func_array(array($stmt, 'bind_param'), $group);
if (!$bound) return false;
if (!$stmt->execute()) return false;
}
if ($inserted) $stmt->close();
return true;
}
该函数将$db
作为mysqli
实例、表名、字段名数组和值引用的平面数组。它在每个查询中最多插入500条记录,并在可能的情况下重新使用准备好的语句。如果所有插入都成功,则返回true
;如果任何插入失败,则返回false
。注意事项:
$values
的长度不是$fields
长度的偶数倍,则最终块可能会在准备阶段失败。$types
参数的长度在大多数情况下应该与$fields
的长度匹配,特别是当其中一些参数不同时。定义了这个函数后,您的示例代码可以替换为以下内容:
$inserts = array();
for ($j = 0; $j < $abilitiesMax - 2; $j++) {
$inserts[] = &$abilityArray[$i]['match_id'];
$inserts[] = &$abilityArray[$i]['player_slot'];
$inserts[] = &$abilityArray[$i][$j]['ability'];
$inserts[] = &$abilityArray[$i][$j]['time'];
$inserts[] = &$abilityArray[$i][$j]['level'];
}
$fields = array('match_id', 'player_slot', 'ability', 'time', 'level');
$result = insertBulkPrepared($db, 'abilities', $fields, 'iiiii', $inserts);
if (!$result) {
echo "<p>$db->error</p>";
echo "<p>ERROR: when trying to insert abilities query</p>";
}
这些符号很重要,因为mysqli_stmt::bind_param
需要引用,而call_user_func_array
在PHP的最新版本中没有提供引用。
您没有给我们最初准备好的语句,因此您很可能需要调整表和字段名。您的代码看起来还像是位于$i
上的循环中;在这种情况下,只有for
循环需要在外循环内部。如果将其他行移到循环之外,则将使用更多的内存来构造$inserts
数组,以获得更高效的批量插入。
我想知道是否可以使用一个准备好的语句插入多行。下面是我通常如何在DB中插入一行的示例: 我要插入的值将来自一个数组,例如:$values[0]['val1'];$values[0]["val2“];$values[0]['val3'];$values[1]['val1'];$values[2]['val2']; 等等。 这段代码可能需要一次插入几百行,我想过创建一个循环来创建数百个参数,然后为每一
问题内容: 使用JDBC(Oracle),我需要在两个表的每一个中插入大约一千行。像这样: 问题在于两个表都是通过公共序列连接的,因此语句的顺序很重要。 如果我只有一张桌子,那会很容易。在这种情况下,我使用了代码: 但是,这种方法只能用一个准备好的语句,因此只能用一个插入。我该如何解决这个问题? 问题答案: 你可以试试 然后
请在关闭之前阅读完整的问题:) 我正在寻找一个有mysqli的准备好的语句(重要的,不是PDO,因为我不能使用它,也不能将一些PDO代码传输到mysqli。),在那里我可以插入一个有很多值(大约2000)的长查询。但是查询必须准备好。 null null null 我的意思是 但当然,我不能把它绑定。
问题内容: 在mysqli准备好的语句中,NULL变成’‘(对于字符串)或0(对于整数)。我想将其存储为真正的NULL。有什么办法吗? 问题答案: 我知道这是一个旧线程,但是可以将真实的NULL值绑定到准备好的语句(请阅读this)。 实际上,您可以使用mysqli_bind_parameter将NULL值传递给数据库。只需创建一个变量并将NULL值(请参见手册页)存储到该变量并将其绑定即可。无论
问题内容: 停止使用不推荐使用的mysql_ *函数后,我切换到mysqli。但是后来,我注意到未准备好的语句对于SQL注入是不安全的。然后,我再次更改了代码。 我所拥有的是以下函数,该函数检查数据库中是否存在变量 $ ID 并打印该行的 title 值: 我将其更改为: 我的问题是:这是执行准备好的语句的正确方法吗?另外,我现在可以安全使用SQL注入吗?非常感谢任何愿意回答这个问题的人:) 问题