-2

我正在尝试创建一个 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用and尝试过%50,两者都不起作用。不断收到应该导致胜利的00000 错误(成功,尽管对我来说它仍然失败,数据库中没有任何内容)

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

UPDATE - 已回答,需要稍作修改,如下所示:

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

4 回答 4

2

您正在PDOmysql_功能混合。选择一个并遵循相应库的错误处理。

$sql将您自己打印出来以查看其格式是否正确也是有益的。此外,如果您正在处理POSTed 数据,您将需要使用准备好的语句

于 2013-05-06T13:28:36.720 回答
1

您可能需要增加默认为 1Mb的max_allowed_pa​​cket值。如果您想分批拆分查询,可以使用模数运算符

$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
}

或者作为一个数组(在此处描述):

$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
}

另外请确保您正确使用准备好的语句 ,这样您就不会受到SQL 注入的攻击。

最后:您可能需要启用错误报告,这样故障就不会沉默;如果在启用错误报告后它们仍然保持沉默(例如error_reporting(-1);),您可能需要将 MySQL 设置为严格模式(不确定这是否有帮助)。如果他们仍然失败,默默地提交错误报告。

编辑mysql_哦,我错过了你正在混合和 PDO 的事实;这可能就是你没有看到任何错误的原因......呃。去阅读关于PDO 错误处理的手册。

@Downvoters:如果您投反对票,至少可以体面地对原因发表评论。

于 2013-05-06T13:28:54.300 回答
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());
    }
}
于 2013-05-06T13:40:30.463 回答
-2

您可能遇到的另一个问题是一个简单的事实,即用户名/信息可能包含无效字符并终止您的命令。举个例子,一个人的姓是“O'Maley”。在构建值字符串并用硬引号括起名称时,您会得到

'奥马利'

大约 8 年前,我遇到了类似的情况,不得不验证数据中的某些值。找到它后,您将知道如何更正每个相应的值,然后返回批处理模式。

另外,考虑某人提供了一个虚假值的虚假值/错误值“--”,这表明行的其余部分是评论......甚至是“;” 表示语句结束。这很可能是您遇到的问题。

正如 RobIII 回应的那样,我的回应太快了,不要一次测试一个,而是查询数据并查看数据中的此类异常/不良逃生帖子。在尝试插入之前修复您需要的内容。

于 2013-05-06T13:39:26.717 回答