PHP PDO ODBC 意外的空结果集

标签 php sql-server pdo

我正在尝试通过 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/

相关文章:

sql - 更新 SQL 表中的数据类型图像

sql-server - 使用 t-sql 脚本启用/禁用 Sql Server 代理

c# - SQLBulkCopy 上传失败时是否有任何数据?

php - 当我从缓存中获取时,fetch 只返回一行

php - 如何使用类似于pdo的mysqli一次插入多条记录

php - 加入两个表?

php - Wordpress 分类法模板不起作用

php - MySQL 查询正在减慢页面加载速度

php - 用随机数填充数组,同时遵守指定的总和、计数和数字边界

php - 只显示正确的电子邮件地址 session ,但显示错误的用户名