foreach中的PDO绑定在准备工作时失败

时间:2018-09-21 19:57:46

标签: php mysql 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附近使用正确的语法            SET survey_id =?,问题'

3 个答案:

答案 0 :(得分:2)

参数名称并不重要。

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

因此,假设这是您的查询

drivers

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

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

ALTER TABLE drivers ADD INDEX (name);

现在,在可以获取参数的循环中,您可以运行准备好的查询1000次,如果需要,可以运行1,000,000次,您所要做的就是将新值绑定到参数并执行查询,该查询将参数值传递给已经准备好(经过编译和优化的查询),并与您在$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);

答案 1 :(得分:1)

这是插入多行数据的方法,您准备一次,然后多次插入// class declaration public class FragmentTopNews extends Fragment implements LoaderManager.LoaderCallbacks<List<NewsItem>>, NewsAdapter.OnItemClickListener{ ... if(activeNetwork != null && activeNetwork.isConnected()){ LoaderManager loaderManager = getLoaderManager(); loaderManager.initLoader(NEWS_LOADER_ID, null,this); } // SwipeRefreshlayout for refreshing the data mSwipeRefreshLayout = rootView.findViewById(R.id.srl_refresher); mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { mNewsAdapter.clearData(); mNewsAdapter.notifyDataSetChanged(); mSwipeRefreshLayout.setRefreshing(true); // Here is the problem getLoaderManager().restartLoader(NEWS_LOADER_ID, null, this); } }); 一条准备好的语句

execute

答案 2 :(得分:1)

准备好的语句的思想是该语句准备一次,然后执行多次。像这样:

$sql = 'INSERT INTO gosurveys_surveys_questions_answers
SET survey_id = :survey_id,
question_id = :question_id,
user_email = :user_email,
answer_type = :answer_type,
question_answer = :question_answer,
question_answer_creation_date = UTC_TIMESTAMP()';

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

foreach($questionsArray as $questionAnswerRow) {
    $query->execute([
        ":survey_id" => $questionAnswerRow["survey_id"],
        // etc.
    ]);
}