PHP PDO BindParam/BindValue 双引号错误
当尝试将参数绑定到 PDO 准备语句时,我得到了非常令人沮丧的结果。
结果是这个错误: 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,了解在第 1 行“items”附近使用的正确语法
该错误清楚地表明表“items”在不应该使用单引号的情况下被用单引号引起来是。我在下面做了一个小测试。正如您所看到的,我一开始并没有将参数放在语句中的引号中,这可能是大多数人的最初猜测。我知道它与 BindParam/BindValue (我已经尝试了相同的结果)函数有关,因为如果您通过将 $params 设置为 null 并在语句中将 ':table' 替换为 'items' 来绕过 bindParams 函数,它工作得很好。
<?php
echo 'started test...';
//connect to database
try {
$dbHandle = new PDO('mysql:dbname=mydatabase;host=mysql.mywebsite.com', 'myuser', 'mypass');
} catch (PDOException $e) {
echo 'Database connection failed: ' . $e->getMessage();
}
//print out the contents of table 'items'
print_r(query("SELECT * FROM :table", array("table" => "items"), $dbHandle));
//the query() function used above
function query($query_str, $params = null, $dbHandle) {
$stmt_obj = $dbHandle->prepare($query_str);
if($params != null) {
bindParams($stmt_obj, $params);
}
$stmt_obj->execute();
//debug stuff
echo '<pre>';
echo 'ERROR: ';
$error = $stmt_obj->errorInfo();
echo $error[2].'<br /><br />';
echo 'DEBUG DUMP:<br />';
$stmt_obj->debugDumpParams();
echo '</pre>';
if (preg_match("/SELECT/i", $query_str)) {
$result = array();
while ($row = $stmt_obj->fetch(PDO::FETCH_ASSOC)) {
array_push($result, $row);
}
unset($stmt_obj);
return $result;
}
}
function bindParams($stmt, $params) {
if(is_object($stmt) && ($stmt instanceof PDOStatement))
{
foreach($params as $key => $value)
{
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = FALSE;
}
if($param) {
$stmt->bindValue(":$key", $value, $param);
}
}
}
有人愿意让我摆脱痛苦并指出我错过的一些非常明显的东西吗?
I'm getting very frustrating results when trying to bind parameters to a PDO prepared statement.
The result is this error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''items'' at line 1
The error clearly shows that the table 'items' is being quoted with single quotes when it shouldn't be. I've put together a little test below. As you can see, I'm not placing the parameters in quotes in the statement to begin with, which would probably be most people's initial guess. I know it has something to do with the BindParam/BindValue (I've tried both with same results) function because if you bypass the bindParams function by setting $params to null and replacing ':table' with 'items' in the statement, it works perfectly fine.
<?php
echo 'started test...';
//connect to database
try {
$dbHandle = new PDO('mysql:dbname=mydatabase;host=mysql.mywebsite.com', 'myuser', 'mypass');
} catch (PDOException $e) {
echo 'Database connection failed: ' . $e->getMessage();
}
//print out the contents of table 'items'
print_r(query("SELECT * FROM :table", array("table" => "items"), $dbHandle));
//the query() function used above
function query($query_str, $params = null, $dbHandle) {
$stmt_obj = $dbHandle->prepare($query_str);
if($params != null) {
bindParams($stmt_obj, $params);
}
$stmt_obj->execute();
//debug stuff
echo '<pre>';
echo 'ERROR: ';
$error = $stmt_obj->errorInfo();
echo $error[2].'<br /><br />';
echo 'DEBUG DUMP:<br />';
$stmt_obj->debugDumpParams();
echo '</pre>';
if (preg_match("/SELECT/i", $query_str)) {
$result = array();
while ($row = $stmt_obj->fetch(PDO::FETCH_ASSOC)) {
array_push($result, $row);
}
unset($stmt_obj);
return $result;
}
}
function bindParams($stmt, $params) {
if(is_object($stmt) && ($stmt instanceof PDOStatement))
{
foreach($params as $key => $value)
{
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = FALSE;
}
if($param) {
$stmt->bindValue(":$key", $value, $param);
}
}
}
Anyone care to put me out of my misery and point out something really obvious that I'm missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
准备好的语句中的符号只是值的占位符,而不是标识符,因此您无法创建具有动态列或表名称的准备好的语句。所有数据库引用都需要在准备时解决。即使这不是真的,PDO/MySQL 如何知道
:table
占位符是文字还是标识符?他们有不同的引用规则。此限制对于所有数据库系统和所有 API 中的预准备语句都很常见。这肯定不是 PDO bug。
The symbols in prepared statements are only placeholders for values, not identifiers, so you can't create a prepared statement with a dynamic column or table name. All database references need to be resolved at prepare-time. Even if this were not true, how would PDO/MySQL know whether the
:table
placeholder was meant to be a literal or an identifier? They have different quoting rules.This restriction is common to prepared statements in all database systems and all APIs. It is certainly not a PDO bug.