我正在尝试创建一个php函数,将数据分成批处理,因为当我尝试相当快地插入它们时它会失败。
我正在尝试将数千条用户数据记录插入同一数据库中的不同格式,稍后将导出到单独的数据库。但是查询失败了。
根据以下评论和答案,我已将代码更新为以下内容。但仍然失败。
代码插入值:
function insertUsers( $users ){
error_reporting(E_ALL);
ini_set('display_errors',1);
global $pdo;
//insert into database
$i = 0;
$base = 'INSERT INTO tth_user_accounts (user_login, user_pass, user_email, user_registered,
user_firstname, user_lastname ) VALUES ';
$sql = '';
var_dump($users);
while( $i < count( $users ) ){
$sql = $sql . ' ("' .
$users[$i]['user_login'] . '", "' .
$users[$i]['user_pass'] . '", "' .
$users[$i]['user_email'] . '", "' .
$users[$i]['user_registered'] . '", "' .
$users[$i]['meta_value']['first_name'] . '", "' .
$users[$i]['meta_value']['last_name'] . '")';
if (!( $i % 25 === 0 )){
$sql = $sql . ', ';
}
if ($i % 25 === 0) {
//execute $base + $query here
$sql = $base . $sql;
$query = $pdo->prepare( $sql );
echo 'check query: <br />';
print_r( $query );
if( $query->execute() ){
echo '50 users succesfully added to the database';
} else {
echo 'Query failed: ';
print_r( $pdo->errorInfo() );
echo '<br />';
}
$sql = ''; //Re-init query string
}
$i++;
}
if ( strlen( $sql ) > 0 ) { // Execute remainder, if any
//execute $base + $query here
$sql = $base . $sql;
$query = $pdo->prepare( $sql );
echo 'check query: <br />';
print_r($query);
if( $query->execute() ){
echo 'User succesfully added to the database';
} else {
echo 'Query failed: ';
print_r( $pdo->errorInfo() );
echo '<br />';
}
}
}
检查查询:
PDOStatement Object ( [queryString] => INSERT INTO tth_user_accounts (user_login, user_pass, user_email, user_registered, user_firstname, user_lastname ) VALUES ("John Smith", "4\/\/350M3 P4sS\/\/0r|)", "john.smith@greatmail.com", "2013-04-11 11:18:58", "John", "Smith") )
查询失败:Array ( [0] => 00000 [1] => [2] => )
使用%25
和%50
进行了尝试,两者都不起作用。继续获得本应导致胜利的00000
error(success,但对我而言仍然失败,数据库中没有任何内容)
如果我有时间,我会手动完成,但这不是一次性事件,所以我需要一个解决这个问题的方法。有没有一种很好的方法可以将查询拆分成批次(以及如何?),这样可以重复查询并一次又一次地执行查询?我一直在关注SO(和其他地方)的一大堆问题,但找不到适合我需求的问题。
更新 - 已经回答,需要进行一些小修改,如下所示:
if (!( $i % 25 === 0 )){
if(!( $i == ( count( $users ) - 1 ))){
$sql = $sql . ', ';
}
}
答案 0 :(得分:2)
您正在将PDO
与mysql_
功能混合使用。选择一个并按照相应库的错误处理。
将$sql
打印给自己以查看其格式是否正确也是有益的。此外,如果您正在处理POST
个数据,则需要使用prepared statements,
答案 1 :(得分:1)
您可能需要增加默认为1Mb的max_allowed_packet值。如果要批量拆分查询,可以使用modulus operator。
$base = 'INSERT INTO ...';
$sql = '';
while( $i < count( $users ) ){
$sql = $sql . ' ("' ... //etc.
if ($i % 50 === 0) {
//execute $base + $qry here
$sql = ''; //Re-init query string
}
}
if (strlen($qry)>0) { // Execute remainder, if any
//execute $base + $query here
}
或作为数组(描述为here):
$base = 'INSERT INTO ...';
$sql = array();
while( $i < count( $users ) ){
$sql[] = ' ("' ... //etc.
if ($i % 50 === 0) {
//execute $base + implode(',', $sql) here
$sql = array(); //Re-init query string
}
}
if (sizeof($qry)>0) { // Execute remainder, if any
//execute $base + implode(',', $sql) here
}
另请确保您正确使用prepared statements ,这样您就不会受到SQL injections的攻击。</ p>
最后:你可能需要启用error reporting,这样失败就不会沉默;如果他们在启用错误报告后仍然保持沉默(例如error_reporting(-1);
),您可能需要将MySQL设置为strict mode(不确定这是否有帮助)。如果他们仍然无法以静默方式提交错误报告。
修改强>
哦,我错过了你混合mysql_
和PDO的事实;这可能就是你没有看到任何错误的原因......呃呃。请阅读PDO error handling上的手册。
@Downvoters:如果你正在贬低至少有礼貌地对为什么发表评论。
答案 2 :(得分:0)
你有没有理由想把它作为一个单一的陈述?为什么不迭代用户并插入每个用户:
while($i < count( $users )) {
$sql = 'INSERT INTO tth_user_accounts (user_login, user_pass, user_email, user_registered, user_firstname, user_lastname ) VALUES ';
$sql = $sql + "(";
$sql = $sql + "'" . $users[$i]['user_login'] . '",';
$sql = $sql + "'" . $users[$i]['user_pass'] . '",';
$sql = $sql + "'" . $users[$i]['user_email'] . '",';
$sql = $sql + "'" . $users[$i]['user_registered'] . '",';
$sql = $sql + "'" . $users[$i]['meta_value']['first_name'] . '",';
$sql = $sql + "'" . $users[$i]['meta_value']['last_name'] . '"';
$sql = $sql + ")";
$query = $pdo->prepare( $sql );
if( $query->execute() ){
echo 'User succesfully added to the database';
} else {
die ("Query failed: " . $pdo->errorInfo());
}
}
更好的是准备语句一次然后绑定参数。正如RobIII所指出的,您可以通过将SQL语句构建为字符串来引入SQL注入漏洞,因此您可以执行以下操作:
$sql = 'INSERT INTO tth_user_accounts (user_login, user_pass, user_email, user_registered, user_firstname, user_lastname) ';
$sql += ' VALUES (:user_login, :user_pass, :user_email, :user_registered, :user_firstname, :user_lastname)';
$query = $pdo->prepare( $sql );
while ($i < count($users)) {
$query->bindParam(":user_login", $users[$i]['user_login']);
$query->bindParam(":user_pass", $users[$i]['user_pass']);
$query->bindParam(":user_email", $users[$i]['user_email']);
$query->bindParam(":user_registered", $users[$i]['user_registered']);
$query->bindParam(":user_firstname", $users[$i]['user_firstname']);
$query->bindParam(":user_lastname", $users[$i]['user_lastname']);
if( $query->execute() ){
echo 'User succesfully added to the database';
} else {
die ("Query failed: " . $pdo->errorInfo());
}
}
答案 3 :(得分:-2)
您可能遇到的另一个问题是一个简单的事实,即用户的姓名/信息可能包含无效字符并终止您的命令。比如一个人的姓氏是“O'Maley”。在构建值字符串并用硬引号包装名称时,您将获得
'O'Maley'
大约8年前,我碰到了与此相似的东西,不得不验证数据中的某些值。一旦找到它,您将知道如何更正每个相应的值,然后返回批处理模式。
另外,如果有人提供虚假值/假值“ - ”的虚假值,则表示其余行是评论......甚至是“;”表示结束陈述。这很可能是你遇到的。
当RobIII做出回应时,我的回答太快了,不要一次测试一个,但查询数据,查看数据中的这些异常/坏转义帖。修复尝试插入之前所需的内容。