Протоколът на клиента MySQL не позволява повече от една заявка да бъде „в ход“. Това означава, че сте изпълнили заявка и сте извадили някои от резултатите, но не всички - след това се опитвате да изпълните втора заявка. Ако първата заявка все още има редове за връщане, втората заявка получава грешка.
Клиентските библиотеки заобикалят това, като извличат всички редовете на първата заявка имплицитно при първото извличане, а след това последващите извличания просто итерират вътрешно кешираните резултати. Това им дава възможност да затворят курсора (що се отнася до MySQL сървъра). Това е "буферираната заявка". Това работи по същия начин като използването на fetchAll(), тъй като и двата случая трябва да заделят достатъчно памет в PHP клиента, за да задържат пълния набор от резултати.
Разликата е, че буферирана заявка държи резултата в MySQL клиентската библиотека, така че PHP не може да получи достъп до редовете, докато не извлечете() всеки ред последователно. Докато fetchAll() незабавно попълва PHP масив за всички резултати, позволявайки ви достъп до произволен ред.
Основната причина не да използвате fetchAll() е, че резултатът може да е твърде голям, за да се побере във вашия PHP memory_limit. Но изглежда, че резултатите от заявката ви така или иначе имат само един ред, така че това не би трябвало да е проблем.
Можете да затворитеCursor(), за да "изпуснете" резултат, преди да извлечете последния ред. MySQL сървърът получава известие, че може да отхвърли този резултат от страната на сървъра и след това можете да изпълните друга заявка. Не трябва да затварятеCursor(), докато не приключите с извличането на даден набор от резултати.
Също така:забелязвам, че изпълнявате своя $stmt2 отново и отново вътре в цикъла, но той ще връща един и същ резултат всеки път. На принципа на преместване на инвариантния на цикъл код извън цикъла, трябва да сте изпълнили това веднъж, преди да стартирате цикъла, и да запишете резултата в PHP променлива. Така че независимо от използването на буферирани заявки или fetchAll(), няма нужда да влагате заявките си.
Затова бих препоръчал да напишете кода си по следния начин:
$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));}
}
Забележка:Аз също използвах именувани параметри вместо позиционни параметри, което улеснява предаването на $row като масив от стойности на параметри. Ако ключовете на масива съвпадат с имената на параметрите, можете просто да предадете масива. В по-старите версии на PHP трябваше да включите :
префикс в клавишите на масива, но това вече не ви е необходимо.
Все пак трябва да използвате mysqlnd. Той има повече функции, по-ефективен е с паметта и лицензът му е съвместим с PHP.