ODBC 准备语句:WHERE 子句中的 CASE
Posted
技术标签:
【中文标题】ODBC 准备语句:WHERE 子句中的 CASE【英文标题】:ODBC Prepared Statement: CASE in WHERE clause 【发布时间】:2014-07-30 08:36:13 【问题描述】:我正在尝试使用 php 的 ODBC 驱动程序在 MSSQL 数据库中进行比较。我正在尝试将用户提供的值与从 CASE 表达式返回的值进行比较。
这行得通:
$r = odbc_prepare($link,"SELECT 'success' WHERE
CASE WHEN 1 = 1 THEN 'foo' ELSE 'bar' END
= 'foo'
");
$s = odbc_execute($r,array());
不幸的是,这会返回一个错误:
$r = odbc_prepare($link,"SELECT 'success' WHERE
CASE WHEN 1 = 1 THEN 'foo' ELSE 'bar' END
= ?
");
$s = odbc_execute($r,array("foo"));
我得到的错误是:
Warning: odbc_execute(): SQL error: [Microsoft][ODBC SQL Server Driver]Syntax error or access violation, SQL state 37000 in SQLDescribeParameter
【问题讨论】:
像.... END = '?'
这样添加引号怎么样?
当然,我试过了。我没有收到错误,但它只是需要“?”作为值,而不是使用提供的参数。
你试过检查准备好的报表日志吗?也许尝试在查询末尾添加FROM DUAL
? (不知道这是否会有所帮助,但尝试一下不会有坏处)
FROM DUAL
只是返回一个语法错误。这不是甲骨文吗?很抱歉不知道在哪里寻找日志,你能启发我吗?我尝试在运行 SQL Profiler 的同时运行它,但它似乎没有在那里输入。
我看到最简单的方法是不使用CASE
,这会导致准备好的语句出现一些问题。所以不用WHERE CASE condition THEN 'foo' ELSE 'bar' END = ?
你可以做WHERE ( condition AND foo = ? ) OR ( !condition AND bar = ? )
。是的,您必须将array("foo","foo")
作为execute
的第二个参数,但我没有看到任何其他解决方案:P
【参考方案1】:
当您在 SQL 中使用参数时,许多 ODBC 包装器(如 PHP 包装器)将尝试调用 SQLDescribeParameter 以了解参数。 MS SQL Server ODBC 驱动程序尝试将您的 SQL 重新排列为一个 select 语句,然后使用标准函数来获取列类型、长度等。对于一些更复杂的 SQL 或不包含表的 SQL(如您的,例如,选择 1)它未能将 SQL 重新排列为有效的选择,您会收到您遇到的错误。
有 2 种解决方案:1) 更改您的 SQL,以便 MS SQL Server ODBC 驱动程序可以将其重新排列为一个选择 2) 更改您的 ODBC 包装器以了解这可能发生并默认为合理的。 Perl 的 DBD::ODBC 执行后者,这意味着人们不必执行前者。
【讨论】:
以上是关于ODBC 准备语句:WHERE 子句中的 CASE的主要内容,如果未能解决你的问题,请参考以下文章
用于返回结果集的 where 子句中的 case 语句包含空值
where 子句中的 case 语句 - SQL Server
具有另一个 sql 语句的 where 子句中的 case 条件