Yanıtlar:
query
standart bir SQL deyimi çalıştırır ve SQL Enjeksiyonlarını ve diğer sorunları önlemek için tüm verilerden düzgün şekilde çıkış yapmanızı gerektirir.
execute
parametrelerden çıkma veya alıntı yapma ihtiyacını ortadan kaldırmak için parametreleri bağlamanıza izin veren hazırlanmış bir deyim çalıştırır. execute
bir sorguyu birden çok kez tekrarlıyorsanız da daha iyi performans gösterir. Hazırlanan ifadelere örnek:
$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();
// $calories or $color do not need to be escaped or quoted since the
// data is separated from the query
En iyi uygulama, hazırlanmış ifadelere bağlı kalmak ve execute
daha fazla güvenlik sağlamaktır .
Ayrıca bkz: PDO tarafından hazırlanan ifadeler SQL enjeksiyonunu önlemek için yeterli mi?
: calories
, mysql_real_escape_string()
enjeksiyonları durdurmaya eşdeğer mi yoksa $sth->bindParam(':calories', $calories);
güvenliği artırmaktan daha fazlasına mı ihtiyacınız var ?
query
bir PDOStatement döndürüyor ? execute
Hayır, aynı değiller. Sağladığı istemci tarafındaki kaçış dışında, hazırlanmış bir ifade sunucu tarafında bir kez derlenir ve ardından her yürütmede farklı parametreler geçirilebilir . Bu, şunları yapabileceğiniz anlamına gelir:
$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);
Küçük ölçekte fark edilmese de genellikle size bir performans artışı sağlarlar. Hazırlanmış ifadeler (MySQL sürümü) hakkında daha fazla bilgi edinin .
Gilean'ın cevabı harika, ancak bazen en iyi uygulamaların nadir istisnaları olduğunu ve en iyi neyin işe yarayacağını görmek için ortamınızı iki şekilde de test etmek isteyebileceğinizi eklemek istedim.
Bir durumda, MS SQL Server içinquery
zayıf bir şekilde desteklenen Microsoft ODBC sürücüsü ile PHP7 çalıştıran bir Ubuntu Linux kutusundan güvenilir verileri toplu olarak transfer ettiğim için bunun amaçlarım için daha hızlı çalıştığını buldum .
Bu soruya ulaştım çünkü hız için sıkıştırmaya çalıştığım bir ETL için uzun süredir çalışan bir komut dosyam vardı. Bana hiç de sezgisel görünüyordu query
daha hızlı olabilir prepare
ve execute
bunun iki yerine tek işlevinin çağrılması çünkü. Parametre bağlama işlemi mükemmel koruma sağlar, ancak pahalı olabilir ve gereksizse önlenebilir.
Birkaç nadir durum göz önüne alındığında :
Microsoft ODBC sürücüsü tarafından desteklenmediği için hazırlanmış bir deyimi yeniden kullanamıyorsanız .
Girdiyi temizleme konusunda endişelenmiyorsanız ve basit kaçış kabul edilebilir. Bunun nedeni, belirli veri türlerinin bağlanmasının Microsoft ODBC sürücüsü tarafından desteklenmemesi olabilir .
PDO::lastInsertId
Microsoft ODBC sürücüsü tarafından desteklenmez.
İşte ortamımı test etmek için kullandığım bir yöntem ve umarım siz bunu çoğaltabilirsiniz veya sizinkinde daha iyi bir şey yapabilirsiniz:
Başlamak için Microsoft SQL Server'da temel bir tablo oluşturdum
CREATE TABLE performancetest (
sid INT IDENTITY PRIMARY KEY,
id INT,
val VARCHAR(100)
);
Ve şimdi performans ölçümleri için temel bir zamanlanmış test.
$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;
}
Benim belirli bir ortamda birden fazla farklı deneme ve sayıları ile oynanan ve sürekli daha hızlı% 20-30 arası sonuçlar elde ettik query
daha prepare
/execute
5,8128969669342 hazırlamak
5,8688418865204 hazırlamak
4,2948560714722 sorgu
4,9533629417419 sorgu
5,9051351547241 hazırlamak
4,332102060318 sorgu
5,9672858715057 hazırlamak
5,0667371749878 sorgu
3,8260300159454 sorgu
4,0791549682617 sorgu
4,3775160312653 sorgu
3,6910600662231 sorgu
hazırlamak 5,2708210945129
6,2671611309052 hazırlamak
7,3791449069977 hazırlamak
6,0673267160143: (7) ortalama hazırlanması
(8) sorgu Ortalama: 4,3276024162769
Bu testin MySQL gibi diğer ortamlarda nasıl karşılaştırıldığını merak ediyorum.