PHP PDO ODBC unerwartete leere Ergebnismenge

Ich versuche, ein Problem mit der Verwendung von PDO über eine ODBC-Verbindung zu einer SQL server-database aufzuspüren, wo ich eine leere Ergebnismenge für eine bekannte gute Abfrage bekomme. Ich würde jede Anleitung von der Gemeinschaft zu schätzen wissen. Dies ist Teil eines großen Systems, an dem ich seit etwa fünf Jahren gearbeitet habe; es nimmt eine XML-Darstellung eines Berichts, generiert SQL von ihm, führt die Abfrage aus, formatiert die Ergebnismenge wie gewünscht und erzeugt eine Webseite für die Präsentation. Mehr als Sie wahrscheinlich wissen müssen, aber ich versuche zu vermitteln, dass ich viel davon verstehe, wie das funktionieren soll und in den meisten Fällen zuverlässig funktioniert. Aber ich habe einen Kunden, der etwas Neues wollte, und es brach mein System.

Ich beziehe mich darauf als eine bekannte gute Abfrage in dem Sinne, dass ich die Abfrage aus meiner Log-file in SSMS (SQL server-Konsole) kopieren und insert kann und es ausführen kann. Es ergibt 62 Reihen von Ergebnissen. Aber wenn ich die gleiche Abfrage durch PDO laufe, errorInfo() ich eine PDOStatement zurück, kein errorInfo() , keine exceptionn geworfen und so weiter. Aber fetchAll() gibt ein leeres Array zurück. Ich war ursprünglich mit query() , aber es schien sicherer zu verwenden prepare() und execute() im Falle gab es etwas, das ich in der Abfrage fehlte. Es hat keinen Unterschied gemacht.

Ich erkenne, dass es typische Umwandlungsprobleme geben kann, aber im folgenden Beispiel sind die beiden abgerufenen Felder vom Typ nvarchar (128) bzw. nvarchar (32), die mit anderen Abfragen erfolgreich zurückkehren.

Ich sollte erwähnen, dass die Abfrage genau einmal in der App ausgeführt wird, also ist es nicht eine Frage von einer vorherigen Ausführung, die das nächste beeinträchtigt, soweit ich es sagen kann. Auch das PDO-object hat setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION);

Hier ist die PDOStatement zurückgegeben von execute ():

 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] ) 

Es ist nicht so komplex, und andere SQL-Abfragen funktionieren gut gegen diese database. Es gibt nur etwas über dieses, das über PDO scheitert, aber arbeitet innerhalb von SSMS.

Irgendwelche Ideen? Hat jemand dieses Verhalten schon einmal gesehen? Gibt es einen anderen path, um zu sehen, was hier los ist? Ich habe einige Fragen zu diesem Thema gesehen, aber alle schienen etwas falsch zu haben, was ich nicht tue.

PHP 5.4.22, übrigens.

Nach dem Brechen deiner Abfrage in ein Format, wie ich es unten benutze, bemerkte ich, dass du explizite Joins (LEFT JOIN, INNER JOIN, etc.) und implizite Joins (FROM table1, table2) gemischt hast. Dies ist nicht nur als eine sehr schlechte Praxis, sondern wurde bekannt, dass ungewöhnliche und unerwartete Abfrage Antworten bei Gelegenheit zu verursachen. Also, wenn ich die implizite Logik deiner Joins betrachte, habe ich die Abfrage wie folgt umgeschrieben:

 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] 

Ich habe die LINKEN JOINs in deiner Abfrage in INNER JOINs geändert, weil die [Item] .SupplierID und [Supplier] .ID in deiner ursprünglichen Abfrage übereinstimmen musste (und damit existiere, da equals nicht einen TRUE-Wert zurückgibt, wenn entweder oder beide Werte sind NULL.) So musste der OrderEntry-Wert auch für eine gültige Antwort zur Rückgabe bestehen. Wenn die Zeile für gültige data vorhanden sein muss, sollten Sie immer einen INNER JOIN verwenden – es vereinfacht die interne Logik und kann oft zu schnelleren Abfrageantworten führen.

Ich weiß, das ist eine alte Frage an dieser Stelle, aber eine gute Antwort ist niemals verschwendet.

Ich bin nicht einverstanden mit deinem Punkt. Wenn ich Hand-Crafting SQL-Abfragen, würden sie kommen, wie Sie Ihre.

Aber der Kontext hier ist abweichend. In diesem System ( http://www.calast.com/DynaCRUX.html ) gibt es eine Abstraktion der databasetabellen und deren Beziehungen, ausgedrückt in XML. Und es gibt eine Abstraktion des gewünschten Berichts, auch in XML. Die App, die SQL erstellt, muss mit den Eingaben umgehen, die es gegeben hat. Manchmal gibt es genügend Informationen, um "gut" SQL wie Sie zu generieren und ich würde schreiben. Und manchmal gibt es nicht, so dass das System das Beste machen kann. Das Fallback ist manchmal pre-ANSI join Syntax.

Auch habe ich darauf hingewiesen, dass (hässlich wie wir es vielleicht denken), die generierte Abfrage (1) ist legal T-SQL, und (2) produziert die Ausgabe der Kunde wollte, wenn in SSMS laufen. Das Problem war nie in der Abfrage, wie sich herausstellt. Es war nur ein configurationserrors in meinem System, also muss ich diese Frage ausschließen.

Das heißt, ich habe vor kurzem die SQL-Generator-Engine umgeschrieben, um einen anderen Ansatz zu verwenden, der Abfragen erzeugt, die viel vernünftiger sind. Das heißt, diejenigen, die so aussehen, wie Sie und ich würden sie schreiben.

Ihre Antwort ist ein guter, und ich vermute, es wird anderen helfen, bessere Fragen zu schreiben.