sql >> Database teknologi >  >> RDS >> Mysql

Årsager til MySQL-fejl 2014 Kan ikke udføre forespørgsler, mens andre ubuffrede forespørgsler er aktive

MySQL-klientprotokollen tillader ikke mere end én forespørgsel at være "i gang". Det vil sige, at du har udført en forespørgsel, og du har hentet nogle af resultaterne, men ikke alle - så prøver du at udføre en anden forespørgsel. Hvis den første forespørgsel stadig har rækker at returnere, får den anden forespørgsel en fejl.

Klientbiblioteker omgår dette ved at hente alle rækkerne af den første forespørgsel implicit ved første hentning, og derefter efterfølgende hentning, itererer blot over de internt cachelagrede resultater. Dette giver dem mulighed for at lukke markøren (hvad angår MySQL-serveren). Dette er den "buffede forespørgsel." Dette fungerer på samme måde som at bruge fetchAll(), idet begge tilfælde skal allokere nok hukommelse i PHP-klienten til at holde det fulde resultatsæt.

Forskellen er, at en bufferforespørgsel holder resultatet i MySQL-klientbiblioteket, så PHP kan ikke få adgang til rækkerne, før du henter() hver række sekventielt. Hvorimod fetchAll() straks udfylder et PHP-array for alle resultaterne, hvilket giver dig adgang til enhver tilfældig række.

Hovedårsagen ikke at bruge fetchAll() er, at et resultat kan være for stort til at passe ind i din PHP memory_limit. Men det ser ud til, at dine forespørgselsresultater kun har én række alligevel, så det burde ikke være et problem.

Du kan lukke Cursor() for at "opgive" et resultat, før du har hentet den sidste række. MySQL-serveren får besked om, at den kan kassere dette resultat på serversiden, og så kan du udføre en anden forespørgsel. Du bør ikke lukke Cursor() før du er færdig med at hente et givet resultatsæt.

Også:Jeg bemærker, at du udfører din $stmt2 igen og igen inde i løkken, men det vil returnere det samme resultat hver gang. På princippet om at flytte loop-invariant kode ud af loopen, skulle du have udført dette én gang, før du starter loopen, og gemt resultatet i en PHP-variabel. Så uanset om du bruger bufferforespørgsler eller fetchAll(), er det ikke nødvendigt for dig at indlejre dine forespørgsler.

Så jeg vil anbefale at skrive din kode på denne måde:

$sql ='SELECT temp_id FROM temp1';
$stmt2 = db::db()->prepare($sql);
$stmt2->execute();
$rs2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
$stmt2->closeCursor();

$sql='SELECT COUNT(*) AS valid FROM cities_has_zipcodes 
      WHERE cities_id=:cities_id AND zipcodes_id=:zipcodes_id';
$stmt1 = db::db()->prepare($sql);

foreach($data AS $row)
{
    try
    {
        $stmt1->execute($row);
        $rs1 = $stmt1->fetchAll(PDO::FETCH_ASSOC);
        $stmt1->closeCursor();
        syslog(LOG_INFO,'$rs1: '.print_r($rs1[0],1).' '.rand());
        syslog(LOG_INFO,'$rs2: '.print_r($rs2[0],1).' '.rand());
    }
    catch(PDOException $e){echo(sql_error($e));}            
}

Bemærk, at jeg også brugte navngivne parametre i stedet for positionelle parametre, hvilket gør det nemmere at videregive $row som rækken af ​​parameterværdier. Hvis nøglerne til arrayet matcher parameternavnene, kan du bare sende arrayet. I ældre versioner af PHP skulle du inkludere : præfiks i array-tasterne, men det behøver du ikke længere.

Du bør alligevel bruge mysqlnd. Den har flere funktioner, den er mere hukommelseseffektiv, og dens licens er kompatibel med PHP.



  1. Sådan returnerer du positionen for et listeelement i MySQL

  2. RUC eller RUR?

  3. Oracle underforespørgsel kan ikke se variablen fra den ydre blok 2 niveauer og op

  4. Sådan finder du alle tabellerne med Identity Column i SQL Server Database - SQL Server / T-SQL Tutorial Del 45