2013-05-24 6 views
9

Jestem w trakcie konwersji niektórych starych stron PHP, aby korzystać z PDO."Aktywny wynik nie zawiera pól" przy użyciu PDO z MS SQL

Poniżej są dwa uproszczone zapytań (nie moje rzeczywiste zapytań) pomoc w zrozumieniu problemu Mam ...

SELECT afield INTO #temptable FROM atable WHERE anotherfield = 'somevalue'; 

SELECT afield,anotherfield,onemorefield FROM atable 
WHERE afield NOT IN (SELECT * FROM #temptable); 

Powyższe zapytanie wyrzuca błąd opisany w tytule (pełniej rzuca „błąd krytyczny: Uncaught wyjątek«PDOException»z komunikatem«SQLSTATE [IMSSP]: aktywna wynik dla zapytania nie zawiera pola.»”)

Gdybym zmienić zapytanie jak to ...

with (SELECT afield INTO #temptable FROM atable 
WHERE anotherfield = 'somevalue') AS temptable; 

SELECT afield,anotherfield,onemorefield FROM atable 
where afield NOT IN (SELECT * FROM temptable); 

To wydaje się ominąć błąd, ale ta wersja zapytania jest okropnie nieefektywna, ponieważ wydaje się, że uruchamia kwerendę podlegającą kuszeniu dla każdego pojedynczego porównania pól w drugim zapytaniu.

Czy istnieje sposób na zrobienie pierwszej formy (która tworzy jednorazowy tabelę raz) przy pracy z PDO?

To działało dobrze na starej stronie, która używała mssql.

EDIT: wiem chyba mogę to zrobić w „niechlujny” sposób, tworząc prawdziwy stół, uruchom go w php, a następnie uruchomić drugą kwerendę (w osobnej rozmowy php), a następnie uruchomić trzecią zapytanie upuścić pierwszy stół. Ale wolałbym nie uciekać się do tego! :)

+0

Należy pamiętać, że słowa kluczowe SQL, takie jak "SELECT, WHERE, FROM ..." powinny być pisane wielkimi literami. Poprawi to czytelność. Powinieneś zacząć od tego pierwszego – hek2mgl

+0

Jeśli nalegasz! . – MrVimes

+0

Czy faktycznie rozdzielasz zapytania średnikiem ';'? – hek2mgl

Odpowiedz

10

Silnik PDO traktuje to zapytanie jako zwracające dwa zestawy wyników (starszy silnik mssql prawdopodobnie po prostu zignorował wszystkie oprócz ostatniego zapytania w ogólnym ciągu zapytania). Udało mi się zrobić to praca przez pomijanie pierwszego zestawu wynik (tymczasowa tabela) za pomocą następującego polecenia

$statement->nextRowset(); 

A następnie za pomocą $statement->fetch(); jako normalnego

31

Jeśli używasz procedury przechowywanej następnie użyć

SET NOCOUNT ON 

Problem polega na tym, że procedura składowana zwraca wynik zawierający liczbę wierszy, których dotyczy pierwszy wynik.

Microsoft Documentation

1

Używam laravel5 i to jak naprawiłem problem;

DB::select("SET ANSI_NULLS ON; SET ANSI_WARNINGS ON;EXEC [storedprocedure] $param1,$param2;"); 
+1

Dzięki Kamaro. Jestem też na Laravel5 i to pomogło. Uruchomiłem 'DB :: select ('SET NOCOUNT ON, EXEC stored_procedure');' i działało idealnie. –

0

Jeśli używasz StoredProcedure i robi coś jak:

DB::select("EXEC [storedprocedure] $param1,$param2;"); 

Zgodnie z powyższym, PDO spodziewa oświadczenie DB::select powrócić jakieś dane. Ale jak twój StoredProcedure nie zwraca żadnych danych, można zmienić DB::select DO DB::update belows:

DB::update("EXEC [storedprocedure] $param1,$param2;"); 

Po tym błędzie nie powinien się już pojawiać.

2

wpadłem na ten temat i powyższe odpowiedzi pomógł, ale odpowiedzi tutaj zakładać rzeczy:

  1. mieć dostęp do modfy się sproc z SET NOCOUNT ON i chcesz zrobić to
  2. jesteś na pewno trzeba przejść do następnego zestawu wierszy $statement->nextRowset();

W moim przypadku używam metody rodzajowe wycofać dane z wielu sprocs gdzie mogą lub nie mogą mieć tego I i musi sprawdzić przed inkrementacją zestawu zestawów wierszy.

użyłem następujące:

while($stmt->columnCount() === 0 && $stmt->nextRowset()) { 
    // Advance rowset until we get to a rowset with data 
} 

if($stmt->columnCount() > 0) { 
    // We found something with data, do stuff. 
    // Code here 
} 

Mam nadzieję, że to pomoże ktoś inny pracuje na podobnym problemie.

Powiązane problemy