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 条件

在 where 子句 SQL 中的 case 语句中使用参数

Oracle:在 Where 子句中使用 Case 语句

如何使用 case 语句来确定存储过程中的 from 和 where 子句?