web-dev-qa-db-ja.com

PHPでのexecとexecuteの違い

私はphpを学んでいますが、私が使用するチュートリアルでは、次のようなものを見ることができます:

$DatabaseAdd->exec('INSERT INTO db_name......

そしてこれ:

$request->execute(array(.....

Execとexecuteに違いはありますか?一方を使用してもう一方を置き換えることはできますか?

9
freij

tl; dr

  • 使用する PDO::exec結果セットを返さない1回限りの準備されていないステートメントを発行します。
  • 使用する PDO::query結果セットを返す1回限りの準備されていないステートメントを発行します。

これらは両方とも、ステートメントが1回だけ実行される場合、および/または準備されたステートメントでサポートされていない方法で動的に構築される場合に役立ちます。通常、ステートメントを適切に構築するために(そしてSQLインジェクションの脆弱性などを回避するために)追加のツールが必要です。それらの柔軟性がめったに必要とされないという事実と相まって、それはそれがしばしば好まれるということを意味します:

  • 使用する PDOStatement::prepareおよびPDOStatement::execute結果を返すかどうかに関係なく、ステートメントを準備して実行します。複数回実行された場合やホットパスで実行された場合に便利です。また、ステートメントの構築を処理するために追加のツールを必要としません。ほとんどの場合、可能な限り推奨されます。

exec および queryPDO オブジェクトに作用するため、接続のコンテキスト内でのみ機能します。 execは、結果セットを返さないステートメント(INSERTUPDATEDELETEなど)に使用され、queryは結果セットを返します(たとえば、SELECTステートメントから)。これらは、本質的に同じことを行う(ステートメントを発行する)ための2つの類似したインターフェースです。 SQLステートメントはそのままサーバーに渡されるため、クライアントの観点からは動的であると見なすことができます。

これが意味することは、理論的には、実行される前に、DBMSによって常に(つまり、すべての呼び出しで)解析、解釈/コンパイルされ、クエリプランに最適化される可能性があるということです。複数回実行すると、パフォーマンスの点でコストがかかります。

実際には、複数回実行するとキャッシュされて再利用されることがよくありますが、DBMSはこれを日和見的にしか実行できず、保証もありません。一致方法によっては、クエリを少し変更すると、DBMSがクエリを完全に再コンパイルする必要がある場合があります。クライアントがクエリを動的に構築する場合があります(プリミティブ文字列の連結を使用する場合が多く、適切な 言語ベース または ライブラリベース ツールのサポートを使用する場合もあります)。クエリプランをキャッシュするDBMS。

更新:好奇心旺盛な方のために、 Pinq はPHPの言語ベースのクエリビルダーの例であり、 Doctrine LDBAL はライブラリベースの例です。 Pinqは述語のPHP式)のみを解析し、残りの部分には 流暢なAPI を使用することに注意してください(流暢なインターフェイスは-のタイプを形成できると考える人もいますが) DSL )。

適切なツールを使用するか、ステートメントが1回だけ(または非常に少ない回数)実行される場合、これは問題なく、場合によっては必要になります。

あなたが知っている場合、おそらく異なるパラメータ(たとえば、述語/ WHERE句の異なる値)でのみ同じステートメントを複数回発行するでしょう、そうではありませんか?クエリプラン全体が確実に破棄されないように、それをDBMSに伝達する方法があれば素晴らしいでしょうか。また、ステートメントが実行される前に(おそらくホットパスで)ステートメントを準備する時間が長くなるため(初期化が遅いフェーズ)、他の方法では実行できないより重い最適化を実行できる可能性があります。

ほとんどのデータベースシステムは、この機能を プリペアドステートメント (さまざまなメカニズム、非標準のAFAIKを使用)の形式で提供します。 PDOは、準備されたステートメントを表す 別のオブジェクト を返す prepare メソッドを介して統一された方法でそれを公開します。

次に、そのオブジェクト、特にその execute メソッド(以前に準備されたステートメントを実行するためにDBMSにステートメントを発行する)を再利用できます。ステートメントがパラメーター化されている場合は、execute呼び出しごとに新しいパラメーターを渡すこともできます。

これにより、ステートメントを作成して発行するために十分に適切なツールを使用する必要があります。前に触れたように、基本的な文字列の連結やその他のアドホックテクニックでは、足を撃つ前に、おそらく escape 動的なパーツ/パラメータを適切に失敗することによって、これまでのところしか得られません。これは SQLインジェクション 脆弱性の最大の原因です。

ステートメントが結果セット(例:SELECT)を返す場合、結果を取得するには、さまざまな fetch バリアントを使用する必要があることに注意してください。

$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();
$result = $sth->fetchAll();
print_r($result);

ソース

また、非常に紛らわしいことに、query自体が結果をPDOStatementオブジェクトの形式で返します(prepareによって返されるものと同じです)。このインターフェースがここで再利用される理由は理解できるかもしれませんが、(控えめに言っても)おそらく最良の設計ではありません。たとえば、(a)明示的に文書化されていないようで、(b)テストしていませんが、executeによって返されたPDOStatementqueryを呼び出すことは違法であると想定します(エラーが発生します)。

免責事項:ドキュメントを解釈するだけで、頻繁に使用するユーザーはもういません。

同様の質問:

16
tne

PDO :: exec()は、単一の関数呼び出しでSQLステートメントを実行し、ステートメントの影響を受ける行数を返します。

したがって、「SELECT」を使用しても、結果は返されません。意味がありますか?

http://php.net/manual/en/pdo.exec.php

3
jdu