PDO的查询与执行

他们都做同样的事情,只是不同?

除了使用之间的prepare之间有什么区别

 $sth = $db->query("SELECT * FROM table"); $result = $sth->fetchAll(); 

 $sth = $db->prepare("SELECT * FROM table"); $sth->execute(); $result = $sth->fetchAll(); 

query运行标准的SQL语句,并要求您正确地转义所有数据以避免SQL注入和其他问题。

execute运行一个准备好的语句,允许您绑定参数以避免需要转义或引用参数。 execute也将执行更好,如果你重复查询多次。 准备报表的示例:

 $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 

最好的做法是坚持准备好的陈述和execute以提高安全性

另请参见: PDO准备的语句是否足以防止SQL注入?

不,他们不一样。 除了它提供的客户端转义之外, 一个准备好的语句在服务器端编译一次,然后可以在每次执行时传递不同的参数 。 这意味着你可以这样做:

 $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); 

他们通常会给你一个性能的提高,虽然小规模并不明显。 阅读更多的准备报表(MySQL版本) 。

Gilean的回答非常好,但是我只想补充一点,有时最好的做法很less有例外,你可能想用两种方法来testing你的环境,看看哪种方法最好。

在一个案例中,我发现query对我的工作更快,因为我是从一个运行PHP7的Ubuntu Linux框中将受信任的数据批量传递给Microsoft SQL Server的微软ODBC驱动程序 。

我遇到了这个问题,因为我有一个ETL的脚本,我正在试图加快速度。 我觉得query可能比prepareexecute更快,因为它只调用一个函数而不是两个函数。 参数绑定操作提供了极好的保护,但是如果不必要的话,这可能是昂贵的,可能会避免。

鉴于几个罕见的条件

  1. 如果您不能重复使用预备的语句,因为它不受Microsoft ODBC驱动程序的支持 。

  2. 如果你不担心消毒input和简单的逃避是可以接受的。 这可能是这种情况,因为Microsoft ODBC驱动程序不支持绑定某些数据types 。

  3. Microsoft ODBC驱动程序不支持PDO::lastInsertId

以下是我用来testing我的环境的一种方法,希望您可以在其中复制它或更好:

首先,我已经在Microsoft SQL Server中创build了一个基本的表

 CREATE TABLE performancetest ( sid INT IDENTITY PRIMARY KEY, id INT, val VARCHAR(100) ); 

现在是性能指标的基本定时testing。

 $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; } 

我在特定的环境中玩过多种不同的testing和计数,并且query结果比prepare / execute结果要持续20-30%

5.8128969669342准备
5.8688418865204准备
4.2948560714722查询
4.9533629417419查询
5.9051351547241准备
4.332102060318查询
5.9672858715057准备
5.0667371749878查询
3.8260300159454查询
4.0791549682617查询
4.3775160312653查询
3.6910600662231查询
5.2708210945129准备
6.2671611309052准备
7.3791449069977准备
(7)准备平均:6.0673267160143
(8)查询平均:4.3276024162769

我很好奇,看看这个testing如何在其他环境中比较,如MySQL。