首页 > 解决方案 > foreach 中的 PDO 绑定在准备时失败

问题描述

我想创建一个可能包含或不包含多个部分的查询。这意味着,我将包含一个数组并循环遍历它,并将查询附加到主 SQL 查询,然后最后准备它。

首先,我定义了sql query

$sql = '';

然后,我定义了一个foreach循环值

$arrayLoopValue = 0;

之后,我创建了一个foreach循环。在其中我增加了arrayLoopValue, 附加了sql一个基于数组索引的新查询。

foreach($questionsArray as $questionAnswerRow){
    $arrayLoopValue = $arrayLoopValue + 1;
    $sql = $sql .
    'INSERT INTO gosurveys_surveys_questions_answers
     SET survey_id = :survey_id_' . $arrayLoopValue .
    ', question_id = :question_id_' . $arrayLoopValue .
    ', user_email = :user_email_' . $arrayLoopValue .
    ', answer_type = :answer_type_' . $arrayLoopValue .
    ', question_answer = :question_answer_' . $arrayLoopValue .
    ', question_answer_creation_date = UTC_TIMESTAMP(); ';
  }

此查询的数据库/示例并不重要,因为所有字段都匹配并且它已经为空。只需要上面提供的结构。

这在以下行失败。

$query = $this->conn->prepare($sql);

我尝试echo查询,看看是否有问题。我得到以下输出:

INSERT INTO gosurveys_surveys_questions_answers
     SET survey_id = :survey_id_1, 
     question_id = :question_id_1, 
     user_email = :user_email_1, 
     answer_type = :answer_type_1, 
     question_answer = :question_answer_1, 
     question_answer_creation_date = UTC_TIMESTAMP(); 

INSERT INTO gosurveys_surveys_questions_answers
     SET survey_id = :survey_id_2, 
     question_id = :question_id_2, 
     user_email = :user_email_2, 
     answer_type = :answer_type_2, 
     question_answer = :question_answer_2, 
     question_answer_creation_date = UTC_TIMESTAMP();

哪个是对的。在这个准备之后,还有第二个foreach循环。prepare但是该函数在语句之后没有到达。

我想知道原因。MYSQL 说明如下:

未捕获的异常“PDOException”,带有消息“SQLSTATE [42000]:语法错误或访问冲突:1064 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在“INSERT INTO gosurveys_surveys_questions_answers SETsurvey_id = ?, ques”附近使用正确的语法

标签: phpmysqlpdo

解决方案


参数的名称并不重要。

如果您想多次运行查询,那么准备它是一个好主意,但参数名称几乎无关紧要。重要的是新值与参数的绑定。

所以让我们假设这是您的查询

$sql = "INSERT INTO gosurveys_surveys_questions_answers
            SET survey_id = :a,
            question_id = :b,
            user_email = :c,
            answer_type = :d,
            question_answer = :e,
            question_answer_creation_date = UTC_TIMESTAMP()";

请注意,参数名称是无关紧要的,只要它们在查询字符串中是唯一的。

所以现在你准备那个查询。这会将基本查询传递到数据库,在该数据库中对其进行编译和优化,但实际上并未运行。

$stmt = $this->conn->prepare($sql);

现在,在获取参数的循环中,如果您愿意,您可以运行准备好的查询 1000、1,000,000 次,您所要做的就是将新值绑定到参数并执行查询,它将参数值传递给已经准备好的 (编译和优化的查询)并使用您传递的数据运行它execute()

foreach($inArray as $array) {
    // build the array of parameters and values

    $params = [ ':a' => $array['field1']
                ':b' => $array['field2']
                ':c' => $array['field3']
                ':d' => $array['field4']
                ':e' => $array['field5']
                ];

    // execute the prepared query using the new parameters
    $stmt->execute($params);
}

推荐阅读