我正在使用通过ODBC连接的MSSQL数据库。
在具有嵌套SELECT语句的查询上使用PDO::bindValue()时,它无法绑定嵌套SELECT中的值(主SELECT没有问题)。这是一段失败的示例代码:
$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()?
发布于 2017-04-14 13:18:10
正如(我从注释中看到的)告诉bindValue传递的值是整数一样,没有解决这个问题.
$stmt->bindValue( "locationid", 1011, PDO::PARAM_INT );...I假设由于某种原因( ? ),不管您在bindValue上指定什么参数为第三个参数,参数都会以字符串的形式进入查询。
然后,我建议通过将值转换为整数就地到查询中来解决这个问题。
在最后一行:
"WHERE st2.LocationID = CAST( :locationid, int ) ))"这不是很优雅,但在您找到用于pdo_odbc的修复/修补程序之前可能是合适的。
--即使这样也不能工作--还有一个更不优雅的解决方案(当然是作为临时修复)。
你写道:
如果我省略了":locationid“的bindValue()并将'1011‘直接插入到查询中,那么调用就会在没有错误的情况下完成,并得到正确的结果。
因此,您可以直接将位置id放在查询中。
假设位置id存储在$locationId中,那么查询的最后一行如下:
"WHERE st2.LocationID = $locationId))");由于这很容易发生sql注入,所以$locationId必须事先进行消毒(或验证)。
这个值必须是一个正整数,所以我建议一种更简单、更防弹的方法,而不是转义它: check $locationId只由数字组成.
if( ! ctype_digit( (string) $locationId ) ) {
// location id is invalid
// do not proceed !
}发布于 2017-04-12 10:15:13
位置ID实际上是作为字符串而不是int存储在MSSQL中吗?当您添加引号时,它有效吗?$stmt->bindValue("locationid","1011",PDO::PARAM_STR);
https://stackoverflow.com/questions/43207071
复制相似问题