PHP PDO ODBC意外的空结果集

时间:2015-07-12 22:29:17

标签: 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。

2 个答案:

答案 0 :(得分:0)

在将您的查询分解为我在下面使用的格式之后,我注意到您正在混合显式连接(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 - 它可以简化内部逻辑,并且通常可以提高查询响应速度。

我意识到这是一个古老的问题,但是一个好的答案永远不会浪费。

答案 1 :(得分:0)

我不同意你的观点。如果我是手工制作SQL查询,它们就会像你的那样出现。

但这里的背景是不同的。在这个系统(http://www.calast.com/DynaCRUX.html)中,有一个以XML表示的数据库表及其关系的抽象。而且,还有一个所需报告的抽象,也是XML。创建SQL的应用程序必须处理它给出的输入。有时会有足够的信息来生成&#34; good&#34;像你和我一样的SQL会写。有时也没有,让系统尽其所能。回退有时是ANSI连接语法之前。

另外,我确实指出(我们可能认为它很丑陋),生成的查询(1)是合法的T-SQL,(2)在SSMS内部运行时产生客户想要的输出。事实证明,问题从未出现在查询中。这只是我系统中的一个配置错误,所以我需要关闭这个问题。

也就是说,我最近重写了SQL生成引擎,使用了一种不同的方法来生成更合理的查询。也就是说,那些看起来像你和我会写它们的那些。

你的答案很好,我怀疑它会帮助其他人写出更好的查询。