Mysql
 sql >> Baza danych >  >> RDS >> Mysql

PDO „Nieprzechwycony wyjątek 'PDOException' .. Nie można wykonywać zapytań, gdy inne zapytania niebuforowane są aktywne. Rozważ użycie PDOStatement::fetchAll().”

Musisz pobierać, dopóki próba pobrania wiersza nie powiedzie się. Wiem, że możesz mieć tylko jeden wiersz w zestawie wyników i uważasz, że jedno pobranie wystarczy, ale tak nie jest (gdy używasz zapytań niebuforowanych). PDO nie wie, ile jest wierszy, dopóki nie dojdzie do końca, gdzie próbuje pobrać następny wiersz, ale się nie udaje.

Prawdopodobnie masz inne stwierdzenia, w których nie udało Ci się w pełni „pobrać, dopóki nie udało się pobrać”. Tak, widzę, że pobierasz, dopóki nie udało się pobrać jednego wypowiedzi, ale to nie znaczy, że zrobiłeś to dla wszystkich.

Wyjaśnienie — kiedy wykonujesz zapytanie za pomocą execute(), tworzysz zestaw wyników, który należy pobrać z bazy danych do php. PDO może obsłużyć tylko 1 z tych „zestawów wyników w toku pobierania” na raz (na połączenie). Musisz całkowicie pobrać zestaw wyników, aż do jego końca, zanim zaczniesz pobierać inny zestaw wyników z innego wywołania funkcji execute().

Kiedy "wywołasz fetch(), dopóki fetch() się nie powiedzie", fakt, że osiągnąłeś koniec wyników, jest wewnętrznie odnotowywany przez PDO, gdy ostatnie wywołanie fetch() nie powiedzie się z powodu braku wyników. PDO jest wtedy usatysfakcjonowane, że wyniki są w pełni pobrane i może wyczyścić wszelkie wewnętrzne zasoby między php a bazą danych, które zostały ustanowione dla tego zestawu wyników, umożliwiając tworzenie/pobieranie innych zapytań.

Istnieją inne sposoby, aby PDO "wywoływać fetch(), dopóki fetch() się nie powiedzie".

  1. Po prostu użyj funkcji fetchAll(), która po prostu pobiera wszystkie wiersze, a więc trafi na koniec zestawu wyników.
  2. lub po prostu wywołaj closeCursor()

*jeśli spojrzysz na źródło closeCursor(), domyślna implementacja dosłownie pobiera wiersze i odrzuca je do końca. Oczywiście jest napisany w c, ale mniej więcej robi to:

function closeCursor() {
    while ($row = $stmt->fetch()) {}
    $this->stmtFullyFetched = true;
}

Niektóre sterowniki db mogą mieć bardziej wydajną implementację, która nie wymaga od nich pobierania wielu wierszy, którymi nikt się nie przejmuje, ale jest to domyślny sposób, w jaki robi to PDO. W każdym razie...

Zwykle nie masz tych problemów, gdy używasz zapytań buforowanych. Powodem jest to, że w przypadku zapytań buforowanych, zaraz po ich wykonaniu, PDO automatycznie w pełni pobierze wyniki bazy danych do pamięci php, więc automatycznie wykonuje część "wywołaj fetch(), dopóki fetch() nie powiedzie się". Kiedy później sam wywołasz fetch() lub fetchAll(), pobiera wyniki z pamięci php, a nie z bazy danych. Zasadniczo zestaw wyników jest natychmiast w pełni pobierany podczas korzystania z buforowanych zapytań, więc nie ma możliwości posiadania więcej niż 1 zestawu wyników w toku pobierania w tym samym czasie (ponieważ php jest jednowątkowe, więc nie ma szans na 2 zapytania uruchomiony w tym samym czasie).

Biorąc pod uwagę to:

$sql = "select * from test.a limit 1";
$stmt = $dbh->prepare($sql);
$stmt->execute(array());

Sposoby pełnego pobrania zestawu wyników (zakładając, że potrzebujesz tylko pierwszego wiersza):

$row = $stmt->fetch();
$stmt->closeCursor();

lub

list($row) = $stmt->fetchAll(); //tricky

lub

$row = $stmt->fetch();
while ($stmt->fetch()) {}


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Parsowanie bardzo dużych plików XML w php

  2. Konwertuj datę w formacie MM/DD/RRRR na datę MySQL

  3. Jaka jest lepsza strategia przechowywania danych dziennika w bazie danych?

  4. Nie można znaleźć błędu w przesłanym kodzie obrazu php

  5. Pomoc Pola wyboru PHP i HTML