我正在尝试通过 ODBC 连接到 SQL Server 数据库来查找使用 PDO 时出现的问题,在该数据库中,我得到了一个已知良好查询的空结果集。我将不胜感激社区的任何指导。这是我已经工作了大约五年的大型系统的一部分;它采用报告的 XML 表示形式,从中生成 SQL,运行查询,按要求格式化结果集,并生成用于展示的网页。比您可能需要知道的更多,但我想表达的是,我很了解它应该如何工作,并且在大多数情况下它可以可靠地工作。但是我有一个客户想要一些新东西,结果我的系统坏了。
我将此称为已知的良好查询,因为我可以将查询从我的日志文件复制并粘贴到 SSMS(SQL Server 控制台)并运行它。它产生 62 行结果。但是当我通过 PDO 运行相同的查询时,我得到一个 PDOStatement,没有 errorInfo()
,没有抛出异常,等等。但是 fetchAll()
返回一个空数组。我最初使用的是 query()
,但使用 prepare()
和 execute()
似乎更安全,以防万一我遗漏了什么在查询中。没有区别。
我意识到可能存在类型转换问题,但在下面的示例中,两个检索字段的类型分别为 nvarchar(128) 和 nvarchar(32),它们与其他查询一起成功返回。
我应该提一下,查询在应用程序中只执行一次,所以据我所知,这不是上一次执行干扰下一次执行的问题。此外,PDO 对象具有 setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
这是 execute() 返回的 PDOStatement:
Result Set PDOStatement Object
(
[queryString] => SELECT [dbo].[Supplier].[SupplierName] AS suppliername,[dbo].[Item].[ItemLookupCode] AS itemlookupcode FROM [dbo].[Order] LEFT JOIN [dbo].[OrderEntry] ON [dbo].[Order].ID=[dbo].[OrderEntry].OrderID LEFT JOIN [dbo].[Item] ON [dbo].[Item].ID=[dbo].[OrderEntry].ItemID,[dbo].[Supplier] WHERE ([dbo].[Order].Time >= '2015-01-01 00:00:00') AND ([dbo].[Order].Time <= '2015-03-31 23:59:59') AND ([dbo].[Item].SupplierID=[dbo].[Supplier].ID) ORDER BY [dbo].[Supplier].[SupplierName]
)
它并没有那么复杂,其他 SQL 查询对这个数据库也能正常工作。关于这个通过 PDO 失败的东西,但在 SSMS 中工作。
有什么想法吗?有没有人见过这种行为?还有其他方法可以查看这里发生了什么吗?我已经查看了关于这个主题的几个问题,但它们似乎都有我没有做的错误。
顺便说一句,PHP 5.4.22。
最佳答案
在将您的查询分解为我在下面使用的格式后,我注意到您混合了显式联接(LEFT JOIN、INNER JOIN 等)和隐式联接(FROM table1、table2)。这不仅被认为是一种非常糟糕的做法,而且众所周知有时会导致异常和意外的查询响应。因此,查看您的联接的隐式逻辑,我将查询重写如下:
SELECT
[dbo].[Supplier].[SupplierName] AS suppliername,
[dbo].[Item].[ItemLookupCode] AS itemlookupcode
FROM [dbo].[Order]
INNER JOIN [dbo].[OrderEntry]
ON [dbo].[Order].ID=[dbo].[OrderEntry].OrderID
INNER JOIN [dbo].[Item]
ON [dbo].[Item].ID=[dbo].[OrderEntry].ItemID
INNER JOIN [dbo].[Supplier]
ON [dbo].[Item].SupplierID=[dbo].[Supplier].ID
WHERE ([dbo].[Order].Time >= '2015-01-01 00:00:00')
AND ([dbo].[Order].Time <= '2015-03-31 23:59:59')
ORDER BY [dbo].[Supplier].[SupplierName]
我将查询中的 LEFT JOIN 更改为 INNER JOIN,因为 [Item].SupplierID 和 [Supplier].ID 必须在您的原始查询中匹配(因此存在,因为 equals 不会返回 TRUE 值如果一个或两个值都为 NULL。)因此,OrderEntry 值也必须存在才能返回有效响应。如果行必须存在才能返回有效数据,您应该始终使用 INNER JOIN - 它简化了内部逻辑并且通常可以导致更快的查询响应。
我意识到这是一个老问题,但绝不会浪费一个好的答案。
关于PHP PDO ODBC 意外的空结果集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31373207/