MySQL PDO Name-Value 仅使用最后一个参数的准备语句
MySQL PDO Name-Value Prepared Statement Using Last Parameter Only
如标题所示,我将 MySQL PDO 与准备好的语句一起使用,并且在执行时,我将单个值(最后提供的值)推送到所有字段中。
Table 看起来像这样:
- id (int - auto-increment)
- a_id(整数)
- b_id(整数)
INSERT 看起来像这样:
INSERT INTO my_table(a_id, b_id)
VALUES (:a_id, :b_id)
要插入的代码如下所示...
$stmt = $conn->prepare($sql);
foreach($params as $k => $v) {
$stmt->bindParam(
$k,
$v
);
}
$stmt->execute();
该语句成功插入一个值(确认 $conn 存在、活动和打开,并且语句已设置且参数已绑定)。
我已经通过在 foreach 内部调试确认了这些值,在那里我得到了两个参数(在 $params 中)“:a_id” => 1, “ :b_id" => 9999...
不过我的记录是 ({new_id}, 9999, 9999)。*
这意味着它看到并使用“:b_id”=> 9999,但似乎删除或覆盖“:a_id”=> 1...
我认为下划线可能是个问题(但显然过去有几个人审查过源代码表明下划线没问题...虽然连字符不是)。
我没有重复使用参数(我的理解是每个准备好的语句允许使用一次)...
这里是否遗漏了一些命名参数问题?因为它基本上是 ->bindParam() 到 ->execute(),所以我没有太多的空间来解决问题。
我正在尝试解决使用 Fat Free Framework 时 ORM-based 数据访问的速度问题,但我认为那里没有干扰。
供参考,这是 运行 在 PHP 5.5.8 / Windows / IIS.
编辑:*
我可以确认移动到位置参数也在做同样的事情。
INSERT INTO my_table(a_id, b_id)
VALUES (?, ?)
代码更改为...
$stmt = $conn->prepare($sql);
$i = 1;
foreach($params as $value) {
$stmt->bindParam(
$i,
$value
);
$i++;
}
$stmt->execute();
阐明 $params 数组是如何设置的……事情被传递给这段代码(这是抽象数据库处理程序的核心),并且数组是手动构造的……
即
$results = \XX\DB::do_cmd(
$db,
self::SQL_INSERT,
array(
':a_id' => intval($this->a_id),
':b_id' => intval($this->b_id),
)
);
还有 ({new_id}, 9999, 9999)...
注意:为了消除混淆,除了进行基于位置的传递之外,我还对值进行了硬编码以查看我会得到什么...
$results = \XX\DB::do_cmd(
$db,
self::SQL_INSERT,
array(
1,
1234,
)
);
我的记录出来了({new_id}, 1234, 1234)。同样的问题,不同的值。
我感觉这里有一个 "gotcha"...但我不知道它是什么。
有趣的是,我根据这两个值(以防止重复)在 INSERT 之前仔细检查 table 是否存在现有记录,并且检查正确地识别出记录在那里...尽管它在数据库中是错误的...这意味着 SELECT 和 INSERT 正在对参数做同样的事情(尽管并不令人惊讶,因为参数处理是相同的)。
编辑 2:
更新说明已解决。使用...
$stmt->execute($params); // scrap the foreach nonsense...
bindValue() 而不是 bindParam() 也是合适的。
注意:我使用的是以下 PHP 文档 (http://php.net/manual/en/pdo.prepared-statements.php),它没有区分 bindValue() 与 bindParam()...
变量必须按引用调用:
$stmt = $conn->prepare($sql);
foreach($params as $k => &$v) {
$stmt->bindParam(
$k,
$v
);
}
$stmt->execute();
在此处查看第一条用户贡献的评论:
感谢大家的帮助!
我采用了 Michael 的解决方案,但也测试了 Ryan 的解决方案。
即
更新说明已解决。使用...
$stmt->execute($params); // scrap the foreach nonsense...
bindValue() 而不是 bindParam() 也是合适的。
最后,根据 Ryan 的评论,我将发布一个答案。
再次感谢!
如标题所示,我将 MySQL PDO 与准备好的语句一起使用,并且在执行时,我将单个值(最后提供的值)推送到所有字段中。
Table 看起来像这样:
- id (int - auto-increment)
- a_id(整数)
- b_id(整数)
INSERT 看起来像这样:
INSERT INTO my_table(a_id, b_id)
VALUES (:a_id, :b_id)
要插入的代码如下所示...
$stmt = $conn->prepare($sql);
foreach($params as $k => $v) {
$stmt->bindParam(
$k,
$v
);
}
$stmt->execute();
该语句成功插入一个值(确认 $conn 存在、活动和打开,并且语句已设置且参数已绑定)。
我已经通过在 foreach 内部调试确认了这些值,在那里我得到了两个参数(在 $params 中)“:a_id” => 1, “ :b_id" => 9999...
不过我的记录是 ({new_id}, 9999, 9999)。*
这意味着它看到并使用“:b_id”=> 9999,但似乎删除或覆盖“:a_id”=> 1...
我认为下划线可能是个问题(但显然过去有几个人审查过源代码表明下划线没问题...虽然连字符不是)。
我没有重复使用参数(我的理解是每个准备好的语句允许使用一次)...
这里是否遗漏了一些命名参数问题?因为它基本上是 ->bindParam() 到 ->execute(),所以我没有太多的空间来解决问题。
我正在尝试解决使用 Fat Free Framework 时 ORM-based 数据访问的速度问题,但我认为那里没有干扰。
供参考,这是 运行 在 PHP 5.5.8 / Windows / IIS.
编辑:*
我可以确认移动到位置参数也在做同样的事情。
INSERT INTO my_table(a_id, b_id)
VALUES (?, ?)
代码更改为...
$stmt = $conn->prepare($sql);
$i = 1;
foreach($params as $value) {
$stmt->bindParam(
$i,
$value
);
$i++;
}
$stmt->execute();
阐明 $params 数组是如何设置的……事情被传递给这段代码(这是抽象数据库处理程序的核心),并且数组是手动构造的……
即
$results = \XX\DB::do_cmd(
$db,
self::SQL_INSERT,
array(
':a_id' => intval($this->a_id),
':b_id' => intval($this->b_id),
)
);
还有 ({new_id}, 9999, 9999)...
注意:为了消除混淆,除了进行基于位置的传递之外,我还对值进行了硬编码以查看我会得到什么...
$results = \XX\DB::do_cmd(
$db,
self::SQL_INSERT,
array(
1,
1234,
)
);
我的记录出来了({new_id}, 1234, 1234)。同样的问题,不同的值。
我感觉这里有一个 "gotcha"...但我不知道它是什么。
有趣的是,我根据这两个值(以防止重复)在 INSERT 之前仔细检查 table 是否存在现有记录,并且检查正确地识别出记录在那里...尽管它在数据库中是错误的...这意味着 SELECT 和 INSERT 正在对参数做同样的事情(尽管并不令人惊讶,因为参数处理是相同的)。
编辑 2:
更新说明已解决。使用...
$stmt->execute($params); // scrap the foreach nonsense...
bindValue() 而不是 bindParam() 也是合适的。
注意:我使用的是以下 PHP 文档 (http://php.net/manual/en/pdo.prepared-statements.php),它没有区分 bindValue() 与 bindParam()...
变量必须按引用调用:
$stmt = $conn->prepare($sql);
foreach($params as $k => &$v) {
$stmt->bindParam(
$k,
$v
);
}
$stmt->execute();
在此处查看第一条用户贡献的评论:
感谢大家的帮助!
我采用了 Michael 的解决方案,但也测试了 Ryan 的解决方案。
即
更新说明已解决。使用...
$stmt->execute($params); // scrap the foreach nonsense...
bindValue() 而不是 bindParam() 也是合适的。
最后,根据 Ryan 的评论,我将发布一个答案。
再次感谢!