首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PDO::bindValue()在使用嵌套SELECT查询时失败

PDO::bindValue()在使用嵌套SELECT查询时失败
EN

Stack Overflow用户
提问于 2017-04-04 12:19:26
回答 2查看 872关注 0票数 8

我正在使用通过ODBC连接的MSSQL数据库。

在具有嵌套SELECT语句的查询上使用PDO::bindValue()时,它无法绑定嵌套SELECT中的值(主SELECT没有问题)。这是一段失败的示例代码:

代码语言:javascript
复制
$stmt = $cmdb->prepare("SELECT ci.CI FROM dbo.cmdb_ci AS ci " .
                       "INNER JOIN dbo.cmdb_model AS m ON m.ModelID = ci.Modelid " .
                       "INNER JOIN dbo.cmdb_class AS c ON c.ClassID = m.Classid " .
                       "WHERE (c.ClassID = :classid) " .
                       "AND (ci.CI IN (SELECT ci2.CI " .
                                      "FROM dbo.cmdb_ci AS ci2 " .
                                      "INNER JOIN dbo.cmdb_ci_status AS st2 ON st2.CI = ci2.CI " .
                                      "WHERE st2.LocationID = :locationid))");
$stmt->bindValue("classid", 13);
$stmt->bindValue("locationid", 1011);
$stmt->execute();
if ($rows = $stmt->fetchAll())
    $stmt->closeCursor();
foreach ($rows as $row)
    echo $row["CI"];

我得到的错误是:

SQLSTATE22018:强制转换规范的无效字符值: 206 MicrosoftSQL ServerOperand类型冲突:文本与int不兼容(SQLExecute206 at SQLExecute206)

如果我省略了用于":locationid“的bindValue()并将'1011‘直接插入到查询中,则调用完成时不会出现错误,并具有正确的结果。

这是PDO中的一个bug,还是必须以不同的方式调用bindValue()?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-14 13:18:10

正如(我从注释中看到的)告诉bindValue传递的值是整数一样,没有解决这个问题.

代码语言:javascript
复制
$stmt->bindValue( "locationid", 1011, PDO::PARAM_INT );

...I假设由于某种原因( ? ),不管您在bindValue上指定什么参数为第三个参数,参数都会以字符串的形式进入查询。

然后,我建议通过将值转换为整数就地到查询中来解决这个问题。

在最后一行:

代码语言:javascript
复制
"WHERE st2.LocationID = CAST( :locationid, int ) ))"

这不是很优雅,但在您找到用于pdo_odbc的修复/修补程序之前可能是合适的。

--即使这样也不能工作--还有一个更不优雅的解决方案(当然是作为临时修复)。

你写道:

如果我省略了":locationid“的bindValue()并将'1011‘直接插入到查询中,那么调用就会在没有错误的情况下完成,并得到正确的结果。

因此,您可以直接将位置id放在查询中。

假设位置id存储在$locationId中,那么查询的最后一行如下:

代码语言:javascript
复制
"WHERE st2.LocationID = $locationId))");

由于这很容易发生sql注入,所以$locationId必须事先进行消毒(或验证)。

这个值必须是一个正整数,所以我建议一种更简单、更防弹的方法,而不是转义它: check $locationId只由数字组成.

代码语言:javascript
复制
if( ! ctype_digit( (string) $locationId ) ) {
    // location id is invalid
    // do not proceed !
}
票数 5
EN

Stack Overflow用户

发布于 2017-04-12 10:15:13

位置ID实际上是作为字符串而不是int存储在MSSQL中吗?当您添加引号时,它有效吗?$stmt->bindValue("locationid","1011",PDO::PARAM_STR);

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43207071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档