6

注意:以下示例中的唯一区别是ORDER BY子句。

好代码:

$sql = 'SELECT [date], ? AS [name] 
FROM [transactions] 
WHERE [category_id] = 10 
GROUP BY [date] 
ORDER BY [date] ASC';

$stmt = $db->prepare($sql);
$stmt->bindValue(1, 'Test', PDO::PARAM_STR);
$stmt->execute();
$data = $stmt->fetchAll();
//returns rows in $data

错误代码:

$sql = 'SELECT [date], ? AS [name] 
FROM [transactions] 
WHERE [category_id] = 10 
GROUP BY [date] 
ORDER BY [date] ASC, [name] ASC';

$stmt = $db->prepare($sql);
$stmt->bindValue(1, 'Test', PDO::PARAM_STR);
$stmt->execute();
$data = $stmt->fetchAll();
//returns an empty array

为什么我的第二个代码块不起作用?如果我直接运行此查询的任一版本(在 SQL Management Studio 中),则无论哪种方式都可以。如果我去掉 PHP 中的问号并将值硬编码到查询中(而不是绑定它),那也可以!这里发生了什么?

更新:这是一个更好地说明问题的示例 PHP 脚本:http: //snipt.org/ALhd1。在这个链接的示例代码中,我包含了 5 个“测试”。测试 #1、2 和 4 都返回结果,而测试 #3 和 5 没有并且应该说明问题。

4

2 回答 2

1

我已经设法重现 PHP 5.4 和 SQL Server 2012 的问题。

问题似乎在于 PDO 的 ODBC 驱动程序。成功的测试使用两个驱动程序给出了相同的结果,但下面使用 test3 作为示例。

使用 Microsoft (3.0) 的本机 SQL Server PHP 驱动程序可以得到正确的结果;

$db = new PDO('sqlsrv:server=.\\SQLEXPRESS');

array(3) { [0]=> string(5) "00000" [1]=> NULL [2]=> NULL }
array(1) { [0]=> array(4) {
    ["date"]=> string(23) "2013-07-23 10:34:24.497"
    [0]=>      string(23) "2013-07-23 10:34:24.497"
    ["name"]=> string(4) "Test"
    [1]=>      string(4) "Test"
  }
}

...在使用 ODBC 运行完全相同的代码时,会给出完全相同的失败结果;

$db = new PDO('odbc:driver={SQL Server Native Client 11.0};server=.\SQLEXPRESS;Trusted_Connection=yes');

array(4) { [0]=>string(5) "00000" [1]=> int(0)  
           [2]=> string(24) " ((null)[0] at (null):0)" [3]=> string(0) "" }
array(0) { }

换句话说,这不是 PDO 本身或 SQL Server 中的限制,而是 ODBC 驱动程序中的限制/错误。

于 2013-07-24T17:12:09.337 回答
0

我试图重现这个问题,但我不能。但是,我怀疑“准备”是在标识一个常量,order by这是一个错误。您可以通过使用显式常量轻松查看错误:

select *
from information_schema.tables t
order by 'a'

这失败并出现错误:

Msg 408, Level 16, State 1, Line 3
A constant expression was encountered in the ORDER BY list, position 1.

也就是说,这有效:

select *, 'a' as name
from information_schema.tables t
order by name;

这是解决问题的建议。尝试使用子查询:

SELECT [date], (select ?) AS [name] 
FROM [transactions] 
WHERE [category_id] = 10 
GROUP BY [date] 
ORDER BY [date] ASC, [name] ASC;

的附加级别select应该在某处说服您的值不是常数(并且仍然为其分配一个值)。

于 2013-07-19T18:39:59.947 回答