query
uruchamia standardową instrukcję SQL i wymaga poprawnej zmiany znaczenia wszystkich danych w celu uniknięcia wstrzyknięć SQL i innych problemów.
execute
uruchamia przygotowaną instrukcję, która pozwala powiązać parametry, aby uniknąć konieczności ucieczki lub cytowania parametrów. execute
będzie również działać lepiej, jeśli będziesz powtarzać zapytanie wiele razy. Przykładowe przygotowane zestawienia:
$sth = $dbh->prepare('SELECT name, colour, calories FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories);
$sth->bindParam(':colour', $colour);
$sth->execute();
Najlepszą praktyką jest trzymanie się przygotowanych oświadczeń i execute
zwiększenie bezpieczeństwa .
Zobacz też: Czy przygotowane instrukcje PDO wystarczą, aby zapobiec wstrzykiwaniu SQL?
: calories
preparatu na to, czy jest to odpowiednikmysql_real_escape_string()
zatrzymania zastrzyków, czy potrzebujesz czegoś więcej niż tylko$sth->bindParam(':calories', $calories);
zwiększenia bezpieczeństwa?query
zwrócić PDOStatement , zamiast bool podobnegoexecute
?Nie, to nie to samo. Oprócz funkcji ucieczki po stronie klienta, którą dostarcza, przygotowana instrukcja jest kompilowana raz po stronie serwera, a następnie może być przekazywana innym parametrom przy każdym wykonaniu. Co oznacza, że możesz:
$sth = $db->prepare("SELECT * FROM table WHERE foo = ?"); $sth->execute(array(1)); $results = $sth->fetchAll(PDO::FETCH_ASSOC); $sth->execute(array(2)); $results = $sth->fetchAll(PDO::FETCH_ASSOC);
Zwykle poprawiają wydajność, chociaż nie są zauważalne na małą skalę. Przeczytaj więcej o przygotowanych wyciągach (wersja MySQL) .
źródło
Odpowiedź Gileana jest świetna, ale chciałem tylko dodać, że czasami zdarzają się rzadkie wyjątki od najlepszych praktyk i możesz chcieć przetestować swoje środowisko w obie strony, aby zobaczyć, co będzie działać najlepiej.
W jednym przypadku okazało się, że
query
działa to szybciej dla moich celów, ponieważ masowo przesyłałem zaufane dane z komputera z systemem Ubuntu Linux z PHP7 ze słabo obsługiwanym sterownikiem Microsoft ODBC dla MS SQL Server .Dotarłem do tego pytania, ponieważ miałem długo działający skrypt dla ETL, który próbowałem wycisnąć dla szybkości. Wydawało mi się intuicyjne, że
query
może być szybsze niżprepare
&,execute
ponieważ wywoływało tylko jedną funkcję zamiast dwóch. Operacja wiązania parametrów zapewnia doskonałą ochronę, ale może być kosztowna i prawdopodobnie można jej uniknąć, jeśli jest niepotrzebna.Biorąc pod uwagę kilka rzadkich warunków :
Jeśli nie możesz ponownie użyć przygotowanej instrukcji, ponieważ nie jest ona obsługiwana przez sterownik Microsoft ODBC .
Jeśli nie martwisz się o odkażanie danych wejściowych i zwykła ucieczka jest do przyjęcia. Może tak być, ponieważ wiązanie pewnych typów danych nie jest obsługiwane przez sterownik Microsoft ODBC .
PDO::lastInsertId
nie jest obsługiwany przez sterownik Microsoft ODBC.Oto metoda, której użyłem do przetestowania mojego środowiska i miejmy nadzieję, że możesz ją odtworzyć lub coś lepszego w swoim:
Na początek utworzyłem podstawową tabelę w Microsoft SQL Server
CREATE TABLE performancetest ( sid INT IDENTITY PRIMARY KEY, id INT, val VARCHAR(100) );
A teraz podstawowy test czasowy dla wskaźników wydajności.
$logs = []; $test = function (String $type, Int $count = 3000) use ($pdo, &$logs) { $start = microtime(true); $i = 0; while ($i < $count) { $sql = "INSERT INTO performancetest (id, val) OUTPUT INSERTED.sid VALUES ($i,'value $i')"; if ($type === 'query') { $smt = $pdo->query($sql); } else { $smt = $pdo->prepare($sql); $smt ->execute(); } $sid = $smt->fetch(PDO::FETCH_ASSOC)['sid']; $i++; } $total = (microtime(true) - $start); $logs[$type] []= $total; echo "$total $type\n"; }; $trials = 15; $i = 0; while ($i < $trials) { if (random_int(0,1) === 0) { $test('query'); } else { $test('prepare'); } $i++; } foreach ($logs as $type => $log) { $total = 0; foreach ($log as $record) { $total += $record; } $count = count($log); echo "($count) $type Average: ".$total/$count.PHP_EOL; }
Grałem z wieloma różnymi próbami i liczyłem w moim specyficznym środowisku i konsekwentnie uzyskuję od 20-30% szybszych wyników z
query
niżprepare
/execute
Jestem ciekawy, jak ten test wypada w porównaniu z innymi środowiskami, takimi jak MySQL.
źródło