MySQL批量插入失败,没有错误

时间:2013-05-06 13:21:44

标签: php mysql

我正在尝试创建一个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 errorsuccess,但对我而言仍然失败,数据库中没有任何内容)

如果我有时间,我会手动完成,但这不是一次性事件,所以我需要一个解决这个问题的方法。有没有一种很好的方法可以将查询拆分成批次(以及如何?),这样可以重复查询并一次又一次地执行查询?我一直在关注SO(和其他地方)的一大堆问题,但找不到适合我需求的问题。

更新 - 已经回答,需要进行一些小修改,如下所示:

if (!( $i % 25 === 0 )){
    if(!( $i == ( count( $users ) - 1 ))){
        $sql = $sql . ', ';
    }
}

4 个答案:

答案 0 :(得分:2)

您正在将PDOmysql_功能混合使用。选择一个并按照相应库的错误处理。

$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做出回应时,我的回答太快了,不要一次测试一个,但查询数据,查看数据中的这些异常/坏转义帖。修复尝试插入之前所需的内容。