在PDO准备语句中,对于多次插入查询执行两次。为什么?

时间:2015-02-17 09:30:34

标签: php mysql pdo

database.php: //database class file

public function multipleInsert($table,$attrArray,$valuesArray) {
        $sql = "INSERT INTO ".$table."(";
        $array =[];
        $appendValues = "";
        $valuesInArray = "";

        foreach ($attrArray as $key => $value) {
            $sql.="".$value.", ";
        }

        $sql = substr_replace($sql,") VALUES ",strlen($sql)-2);

        foreach ($valuesArray as $valArr) {
            $valuesInArray.= "(";
            foreach ($valArr as $key => $value) {
                array_push($array, $value);
                $valuesInArray.="?,";
            }
            $appendValues.= substr_replace($valuesInArray,"),",strlen($valuesInArray)-1);
            $valuesInArray = "";
        }
        $appendValues = substr_replace($appendValues,"",strlen($appendValues)-1);
        $sql.=$appendValues;
        //die($sql);
        $result = $this->executeQueryPRE($sql,$array);
        return $result;
    }

private function executeQueryPRE($sql,$arr) {
        try{
            $executeSQL = $this->Connection->prepare($sql);
            print_r($executeSQL);die();
            $executeSQL->execute($arr);
            if($executeSQL) {
                if($this->Connection->lastInsertId())
                    return $this->Connection->lastInsertId();
                else
                    return true;
            }
            else
                return false;
        }
        catch (PDOException $e) {
          print "Error!: " . $e->getMessage() . "<br/>";
          die();
        }
    }

sample.php //利用多个插入查询的示例文件

require_once("database.php");
$Database = new Database;
    $arr = ["ct_name","ct_num","ct_status"];
    $arr1 = [["x","1234567890",1],["y","1234567890",1],["z","1234567890",1],["a","1234567890",1]];
    $Database->multipleInsert("contact",$arr,$arr1);

使用PDO prepare语句,我正在尝试开发动态多插入查询。当我尝试执行它时,值将被插入表中两次。我在执行它之前已经去了print_r($ executeSQL)和die()选项,它显示了一个正确的多插入查询,如下所示。

  

PDOStatement对象([queryString] =&gt; INSERT INTO contact(ct_name,   ct_num,ct_status)VALUES(?,?,?),(?,?,?),(?,?,?),(?,?,?))

为什么插入两次,原因是什么?如何克服这个问题?

1 个答案:

答案 0 :(得分:1)

不是您实际问题的答案,但可能是您要解决的实际问题:

我不认为这个字符串连续的东西值得任何麻烦 php脚本执行时间越长,污染MySQL查询缓存,容易出错 因此,除非你能指出一个非常非常具体的问题,我认为它在所有方面都会失败:只需准备一个语句并多次执行它。

<?php
/*
table must be a valid table identifier
columns must be an array of valid field identifiers
recordData is an array of records, each itself an array of corresponding values for the fields in $columns
  recordData is the only parameter for which proper encoding is taken care of by this function
*/
function foo($table, $columns, $recordData) {
    $query = sprintf('
        INSERT INTO %s (%s) VALUES (%s)
    ',
        $table,
        join(',', $columns) /* put in the field ids like a,b,c,d */,
        join(',', array_pad(array(), count($columns), '?')) /* put in a corresponding number of ? placeholders like ?,?,?,? */
    );
    // resulting query string looks like INSERT INTO tablename (a,b,c,d) VALUES (?,?,?,?)
    // let the MySQL server prepare that query
    $stmt = $yourPDOInstance->prepare($query);
    // it might fail -> check if your error handling is in place here....

    // now just iterate through the data array and use each record as the data source for the prepapred statement
    // this will (more or less) only transmit the statement identifier (which the MySQL server returned as the result of pdo::prepare)
    // and the actual payload data
    // .... as long as $yourPDOInstance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); has been set somewhere prior to the prepare....
    foreach( $recordData as $record ) {
        $stmt->execute( $record );
        // might fail, so again: check your error handling ....
    }
}

$cols = ["ct_name","ct_num","ct_status"];
$data = [
    ["x","1234567890",1],
    ["y","1234567890",1],
    ["z","1234567890",1],
    ["a","1234567890",1],
];

foo("contact", $cols, $data);

(脚本仅由php -l测试;无保修)

另见:http://docs.php.net/pdo.prepared-statements