<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/mysqli.quickstart.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ja',
  ),
  'this' => 
  array (
    0 => 'mysqli.quickstart.prepared-statements.php',
    1 => 'プリペアドステートメント',
    2 => 'プリペアドステートメント',
  ),
  'up' => 
  array (
    0 => 'mysqli.quickstart.php',
    1 => 'クイックスタートガイド',
  ),
  'prev' => 
  array (
    0 => 'mysqli.quickstart.statements.php',
    1 => 'ステートメントの実行',
  ),
  'next' => 
  array (
    0 => 'mysqli.quickstart.stored-procedures.php',
    1 => 'ストアドプロシージャ',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    'path' => 'reference/mysqli/quickstart.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="mysqli.quickstart.prepared-statements" class="section">
  <h2 class="title">プリペアドステートメント</h2>
  <p class="para">
   MySQL データベースは、
   プリペアドステートメントをサポートしています。
   プリペアドステートメント、
   またはパラメータ化したステートメントは、
   同じステートメントを繰り返し、
   高い効率で実行すると同時に、
   SQLインジェクションから守ります。
  </p>
  <p class="para">
   <strong>基本的なワークフロー</strong>
  </p>
  <p class="para">
   プリペアドステートメントの実行は、
   ふたつの段階を踏んで行われます:
   準備と実行です。
   準備の段階では、
   ステートメントのテンプレートがデータベースサーバーに送信されます。
   サーバーは文法のチェックを行い、
   サーバーの内部リソースを後に再利用するために初期化しておきます。
  </p>
  <p class="para">
   MySQL サーバーは名前を指定せず、
   位置を指定できるプレースホルダーを
   <code class="literal">?</code> によってサポートしています。
  </p>
  <p class="para">
   準備の後、実行が行われます。
   実行する間、
   クライアントはパラメータの値をバインドし、サーバーに送信します。
   サーバーはステートメントをバインドされた値とともに、
   以前作成した内部リソースを使って実行します。
  </p>
  <p class="para">
   <div class="example" id="example-1">
    <p><strong>例1 プリペアドステートメント</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />mysqli_report</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_REPORT_ERROR </span><span style="color: #007700">| </span><span style="color: #0000BB">MYSQLI_REPORT_STRICT</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli </span><span style="color: #007700">= new </span><span style="color: #0000BB">mysqli</span><span style="color: #007700">(</span><span style="color: #DD0000">"example.com"</span><span style="color: #007700">, </span><span style="color: #DD0000">"user"</span><span style="color: #007700">, </span><span style="color: #DD0000">"password"</span><span style="color: #007700">, </span><span style="color: #DD0000">"database"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Non-prepared statement */<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"DROP TABLE IF EXISTS test"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test(id INT, label TEXT)"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Prepared statement, stage 1: prepare */<br /></span><span style="color: #0000BB">$stmt </span><span style="color: #007700">= </span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prepare</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO test(id, label) VALUES (?, ?)"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Prepared statement, stage 2: bind and execute */<br /></span><span style="color: #0000BB">$id </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$label </span><span style="color: #007700">= </span><span style="color: #DD0000">'PHP'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bind_param</span><span style="color: #007700">(</span><span style="color: #DD0000">"is"</span><span style="color: #007700">, </span><span style="color: #0000BB">$id</span><span style="color: #007700">, </span><span style="color: #0000BB">$label</span><span style="color: #007700">); </span><span style="color: #FF8000">// "is" means that $id is bound as an integer and $label as a string<br /><br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">execute</span><span style="color: #007700">();</span></span></code></div>
    </div>

   </div>
  </p>
  <p class="para">
   <strong>繰り返し実行させる</strong>
  </p>
  <p class="para">
   プリペアドステートメントは、
   繰り返し実行させることができます。
   実行させる度に、
   バインドされた現在の値が評価され、
   サーバーに送られます。
   ステートメントは再度パースされません。
   ステートメントのテンプレートもサーバーに再度送信されません。
  </p>
  <p class="para">
   <div class="example" id="example-2">
    <p><strong>例2 INSERT を一度だけ準備し、複数回実行する</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />mysqli_report</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_REPORT_ERROR </span><span style="color: #007700">| </span><span style="color: #0000BB">MYSQLI_REPORT_STRICT</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli </span><span style="color: #007700">= new </span><span style="color: #0000BB">mysqli</span><span style="color: #007700">(</span><span style="color: #DD0000">"example.com"</span><span style="color: #007700">, </span><span style="color: #DD0000">"user"</span><span style="color: #007700">, </span><span style="color: #DD0000">"password"</span><span style="color: #007700">, </span><span style="color: #DD0000">"database"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Non-prepared statement */<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"DROP TABLE IF EXISTS test"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test(id INT, label TEXT)"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Prepared statement, stage 1: prepare */<br /></span><span style="color: #0000BB">$stmt </span><span style="color: #007700">= </span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prepare</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO test(id, label) VALUES (?, ?)"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Prepared statement, stage 2: bind and execute */<br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bind_param</span><span style="color: #007700">(</span><span style="color: #DD0000">"is"</span><span style="color: #007700">, </span><span style="color: #0000BB">$id</span><span style="color: #007700">, </span><span style="color: #0000BB">$label</span><span style="color: #007700">); </span><span style="color: #FF8000">// "is" means that $id is bound as an integer and $label as a string<br /><br /></span><span style="color: #0000BB">$data </span><span style="color: #007700">= [<br />    </span><span style="color: #0000BB">1 </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'PHP'</span><span style="color: #007700">,<br />    </span><span style="color: #0000BB">2 </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'Java'</span><span style="color: #007700">,<br />    </span><span style="color: #0000BB">3 </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'C++'<br /></span><span style="color: #007700">];<br />foreach (</span><span style="color: #0000BB">$data </span><span style="color: #007700">as </span><span style="color: #0000BB">$id </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$label</span><span style="color: #007700">) {<br />    </span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">execute</span><span style="color: #007700">();<br />}<br /><br /></span><span style="color: #0000BB">$result </span><span style="color: #007700">= </span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">'SELECT id, label FROM test'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$result</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">fetch_all</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_ASSOC</span><span style="color: #007700">));</span></span></code></div>
    </div>

    <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
    <div class="example-contents screen">
<div class="cdata"><pre>
array(3) {
  [0]=&gt;
  array(2) {
    [&quot;id&quot;]=&gt;
    string(1) &quot;1&quot;
    [&quot;label&quot;]=&gt;
    string(3) &quot;PHP&quot;
  }
  [1]=&gt;
  array(2) {
    [&quot;id&quot;]=&gt;
    string(1) &quot;2&quot;
    [&quot;label&quot;]=&gt;
    string(4) &quot;Java&quot;
  }
  [2]=&gt;
  array(2) {
    [&quot;id&quot;]=&gt;
    string(1) &quot;3&quot;
    [&quot;label&quot;]=&gt;
    string(3) &quot;C++&quot;
  }
}
</pre></div>
    </div>
   </div>
  </p>
  <p class="para">
   プリペアドステートメントごとに、
   サーバーのリソースが消費されます。
   ステートメントは、使った後はすぐに閉じるべきです。
   それを明示的に行わない場合、
   ステートメントハンドルが PHP によって開放された後、
   ステートメントが閉じられます。
  </p>
  <p class="para">
   プリペアドステートメントが、
   ステートメントを実行するもっとも効率が良い方法とは限りません。
   プリペアドステートメントが一度しか実行されないと、
   クライアントとサーバー間の通信が、
   ステートメントを準備しない場合と比べて余計に行われてしまいます。
   よって、上の例の <code class="literal">SELECT</code>
   は、プリペアドステートメントを使って実行していません。
  </p>
  <p class="para">
   また、
   MySQL の複数INSERT の文法を使うことも検討してみて下さい。
   たとえば、複数INSERT によって、
   サーバーとクライアント間に必須の通信が、
   上に示すプリペアドステートメントの例よりも少なくなります。
  </p>
  <p class="para">	
   <div class="example" id="example-3">	
    <p><strong>例3 複数INSERTを使い、クライアント・サーバー間の通信を減らす</strong></p>	
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />mysqli_report</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_REPORT_ERROR </span><span style="color: #007700">| </span><span style="color: #0000BB">MYSQLI_REPORT_STRICT</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli </span><span style="color: #007700">= new </span><span style="color: #0000BB">mysqli</span><span style="color: #007700">(</span><span style="color: #DD0000">"example.com"</span><span style="color: #007700">, </span><span style="color: #DD0000">"user"</span><span style="color: #007700">, </span><span style="color: #DD0000">"password"</span><span style="color: #007700">, </span><span style="color: #DD0000">"database"</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"DROP TABLE IF EXISTS test"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test(id INT)"</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$values </span><span style="color: #007700">= [</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">, </span><span style="color: #0000BB">3</span><span style="color: #007700">, </span><span style="color: #0000BB">4</span><span style="color: #007700">];<br /><br /></span><span style="color: #0000BB">$stmt </span><span style="color: #007700">= </span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prepare</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO test(id) VALUES (?), (?), (?), (?)"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bind_param</span><span style="color: #007700">(</span><span style="color: #DD0000">'iiii'</span><span style="color: #007700">, ...</span><span style="color: #0000BB">$values</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">execute</span><span style="color: #007700">();</span></span></code></div>
    </div>
	
   </div>	
  </p>
  <p class="para">
   <strong>結果セットの値のデータ型</strong>
  </p>
  <p class="para">
   MySQL のクライアントサーバープロトコルは、
   プリペアドステートメントと、
   準備しないステートメントとでは異なるデータ転送プロトコルを使います。
   プリペアドステートメントは、いわゆるバイナリプロトコルを使います。
   MySQL は結果セットのデータを、
   バイナリフォーマットで &quot;そのまま&quot; 送信します。
   結果セットは送信される前は文字列にシリアライズされていません。
   クライアントライブラリは、
   バイナリデータを受け取って値を適切なPHP のデータ型に変換しようとします。
   たとえば、<code class="literal">INT</code>
   として定義されたカラムからの結果は、
   PHP の整数値として提供されます。
  </p>
  <p class="para">
   <div class="example" id="example-4">
    <p><strong>例4 ネイティブのデータ型</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />mysqli_report</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_REPORT_ERROR </span><span style="color: #007700">| </span><span style="color: #0000BB">MYSQLI_REPORT_STRICT</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli </span><span style="color: #007700">= new </span><span style="color: #0000BB">mysqli</span><span style="color: #007700">(</span><span style="color: #DD0000">"example.com"</span><span style="color: #007700">, </span><span style="color: #DD0000">"user"</span><span style="color: #007700">, </span><span style="color: #DD0000">"password"</span><span style="color: #007700">, </span><span style="color: #DD0000">"database"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Non-prepared statement */<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"DROP TABLE IF EXISTS test"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test(id INT, label TEXT)"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO test(id, label) VALUES (1, 'PHP')"</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$stmt </span><span style="color: #007700">= </span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prepare</span><span style="color: #007700">(</span><span style="color: #DD0000">"SELECT id, label FROM test WHERE id = 1"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">execute</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$result </span><span style="color: #007700">= </span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">get_result</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$row </span><span style="color: #007700">= </span><span style="color: #0000BB">$result</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">fetch_assoc</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">"id = %s (%s)\n"</span><span style="color: #007700">, </span><span style="color: #0000BB">$row</span><span style="color: #007700">[</span><span style="color: #DD0000">'id'</span><span style="color: #007700">], </span><span style="color: #0000BB">gettype</span><span style="color: #007700">(</span><span style="color: #0000BB">$row</span><span style="color: #007700">[</span><span style="color: #DD0000">'id'</span><span style="color: #007700">]));<br /></span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">"label = %s (%s)\n"</span><span style="color: #007700">, </span><span style="color: #0000BB">$row</span><span style="color: #007700">[</span><span style="color: #DD0000">'label'</span><span style="color: #007700">], </span><span style="color: #0000BB">gettype</span><span style="color: #007700">(</span><span style="color: #0000BB">$row</span><span style="color: #007700">[</span><span style="color: #DD0000">'label'</span><span style="color: #007700">]));</span></span></code></div>
    </div>

    <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
    <div class="example-contents screen">
<div class="cdata"><pre>
id = 1 (integer)
label = PHP (string)
</pre></div>
    </div>
   </div>
  </p>
  <p class="para">
   この振る舞いが、準備しないステートメントの場合は異なります。
   デフォルトでは、準備しないステートメントの結果は、
   全て文字列として返されます。
   このデフォルトは、接続オプションで変更できます。
   接続オプションを使うと、この振る舞いの違いはなくなります。
  </p>
  <p class="para">
   <strong>バインドされた値を使って、結果を取得する</strong>
  </p>
  <p class="para">
   プリペアドステートメントからの結果は、
   出力値をバインドして取得することもできますし、
   <span class="classname"><a href="class.mysqli-result.php" class="classname">mysqli_result</a></span>
   から取得するようにリクエストすることもできます。
  </p>
  <p class="para">
   出力変数は、ステートメントの実行後にバインドしなければいけません。
   ステートメントの結果セットのそれぞれのカラムごとに、
   ひとつの値をバインドしなければいけません。
  </p>
  <p class="para">
   <div class="example" id="example-5">
    <p><strong>例5 バインドされた値を出力する</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />mysqli_report</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_REPORT_ERROR </span><span style="color: #007700">| </span><span style="color: #0000BB">MYSQLI_REPORT_STRICT</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli </span><span style="color: #007700">= new </span><span style="color: #0000BB">mysqli</span><span style="color: #007700">(</span><span style="color: #DD0000">"example.com"</span><span style="color: #007700">, </span><span style="color: #DD0000">"user"</span><span style="color: #007700">, </span><span style="color: #DD0000">"password"</span><span style="color: #007700">, </span><span style="color: #DD0000">"database"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Non-prepared statement */<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"DROP TABLE IF EXISTS test"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test(id INT, label TEXT)"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO test(id, label) VALUES (1, 'PHP')"</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$stmt </span><span style="color: #007700">= </span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prepare</span><span style="color: #007700">(</span><span style="color: #DD0000">"SELECT id, label FROM test WHERE id = 1"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">execute</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bind_result</span><span style="color: #007700">(</span><span style="color: #0000BB">$out_id</span><span style="color: #007700">, </span><span style="color: #0000BB">$out_label</span><span style="color: #007700">);<br /><br />while (</span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">fetch</span><span style="color: #007700">()) {<br />    </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">"id = %s (%s), label = %s (%s)\n"</span><span style="color: #007700">, </span><span style="color: #0000BB">$out_id</span><span style="color: #007700">, </span><span style="color: #0000BB">gettype</span><span style="color: #007700">(</span><span style="color: #0000BB">$out_id</span><span style="color: #007700">), </span><span style="color: #0000BB">$out_label</span><span style="color: #007700">, </span><span style="color: #0000BB">gettype</span><span style="color: #007700">(</span><span style="color: #0000BB">$out_label</span><span style="color: #007700">));<br />}</span></span></code></div>
    </div>

    <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
    <div class="example-contents screen">
<div class="cdata"><pre>
id = 1 (integer), label = PHP (string)
</pre></div>
    </div>
   </div>
  </p>
  <p class="para">
   プリペアドステートメントは、
   デフォルトでは、結果セットをバッファリングせずに返します。
   ステートメントの結果は、
   暗黙のうちに取得されることはありませんし、
   サーバーからクライアントに、
   バッファリングされるためにデータが送信されることもありません。
   結果セットは、全ての結果がクライアントによって取得されるまで、
   サーバーのリソースを消費します。
   よって、結果は必要に応じて取得することが推奨されます。
   クライアントが全ての結果を取得できなかったり、
   クライアントが全てのデータを取得する前にステートメントを閉じたりした場合、
   <code class="literal">mysqli</code> は暗黙のうちにデータを取得しなければいけません。
  </p>
  <p class="para">
   プリペアドステートメントであっても、
   <span class="methodname"><a href="mysqli-stmt.store-result.php" class="methodname">mysqli_stmt::store_result()</a></span>
   を使って結果をバッファリングすることが可能です。
  </p>
  <p class="para">
   <strong>mysqli_result インターフェイスを使って、結果を取得する</strong>
  </p>
  <p class="para">
   バインドされた結果を使う代わりに、
   mysqli_result インターフェイスを使って結果を取得することもできます。
   <span class="methodname"><a href="mysqli-stmt.get-result.php" class="methodname">mysqli_stmt::get_result()</a></span>
   は、バッファリングされた結果セットを返します。
  </p>
  <p class="para">
   <div class="example" id="example-6">
    <p><strong>例6 結果を取得するために、mysqli_result を使う</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />mysqli_report</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_REPORT_ERROR </span><span style="color: #007700">| </span><span style="color: #0000BB">MYSQLI_REPORT_STRICT</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli </span><span style="color: #007700">= new </span><span style="color: #0000BB">mysqli</span><span style="color: #007700">(</span><span style="color: #DD0000">"example.com"</span><span style="color: #007700">, </span><span style="color: #DD0000">"user"</span><span style="color: #007700">, </span><span style="color: #DD0000">"password"</span><span style="color: #007700">, </span><span style="color: #DD0000">"database"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Non-prepared statement */<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"DROP TABLE IF EXISTS test"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test(id INT, label TEXT)"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO test(id, label) VALUES (1, 'PHP')"</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$stmt </span><span style="color: #007700">= </span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prepare</span><span style="color: #007700">(</span><span style="color: #DD0000">"SELECT id, label FROM test WHERE id = 1"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">execute</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$result </span><span style="color: #007700">= </span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">get_result</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$result</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">fetch_all</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_ASSOC</span><span style="color: #007700">));</span></span></code></div>
    </div>

    <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
    <div class="example-contents screen">
<div class="cdata"><pre>
array(1) {
  [0]=&gt;
  array(2) {
    [&quot;id&quot;]=&gt;
    int(1)
    [&quot;label&quot;]=&gt;
    string(3) &quot;PHP&quot;
  }
}
</pre></div>
    </div>
   </div>
  </p>
  <p class="para">
   <span class="classname"><a href="class.mysqli-result.php" class="classname">mysqli_result</a></span>
   インターフェイスを使うと、
   クライアント側で結果セットを柔軟に操作することができます。
  </p>
  <p class="para">
   <div class="example" id="example-7">
    <p><strong>例7 柔軟に結果を読み取るために、バッファリングされた結果セットを使う</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />mysqli_report</span><span style="color: #007700">(</span><span style="color: #0000BB">MYSQLI_REPORT_ERROR </span><span style="color: #007700">| </span><span style="color: #0000BB">MYSQLI_REPORT_STRICT</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli </span><span style="color: #007700">= new </span><span style="color: #0000BB">mysqli</span><span style="color: #007700">(</span><span style="color: #DD0000">"example.com"</span><span style="color: #007700">, </span><span style="color: #DD0000">"user"</span><span style="color: #007700">, </span><span style="color: #DD0000">"password"</span><span style="color: #007700">, </span><span style="color: #DD0000">"database"</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Non-prepared statement */<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"DROP TABLE IF EXISTS test"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test(id INT, label TEXT)"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">query</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO test(id, label) VALUES (1, 'PHP'), (2, 'Java'), (3, 'C++')"</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$stmt </span><span style="color: #007700">= </span><span style="color: #0000BB">$mysqli</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prepare</span><span style="color: #007700">(</span><span style="color: #DD0000">"SELECT id, label FROM test"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">execute</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$result </span><span style="color: #007700">= </span><span style="color: #0000BB">$stmt</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">get_result</span><span style="color: #007700">();<br /><br />for (</span><span style="color: #0000BB">$row_no </span><span style="color: #007700">= </span><span style="color: #0000BB">$result</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">num_rows </span><span style="color: #007700">- </span><span style="color: #0000BB">1</span><span style="color: #007700">; </span><span style="color: #0000BB">$row_no </span><span style="color: #007700">&gt;= </span><span style="color: #0000BB">0</span><span style="color: #007700">; </span><span style="color: #0000BB">$row_no</span><span style="color: #007700">--) {<br />    </span><span style="color: #0000BB">$result</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">data_seek</span><span style="color: #007700">(</span><span style="color: #0000BB">$row_no</span><span style="color: #007700">);<br />    </span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$result</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">fetch_assoc</span><span style="color: #007700">());<br />}</span></span></code></div>
    </div>

    <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
    <div class="example-contents screen">
<div class="cdata"><pre>
array(2) {
  [&quot;id&quot;]=&gt;
  int(3)
  [&quot;label&quot;]=&gt;
  string(3) &quot;C++&quot;
}
array(2) {
  [&quot;id&quot;]=&gt;
  int(2)
  [&quot;label&quot;]=&gt;
  string(4) &quot;Java&quot;
}
array(2) {
  [&quot;id&quot;]=&gt;
  int(1)
  [&quot;label&quot;]=&gt;
  string(3) &quot;PHP&quot;
}
</pre></div>
    </div>
   </div>
  </p>
  <p class="para">
   <strong>エスケープと SQL インジェクション</strong>
  </p>
  <p class="para">
   バインドされる変数は、
   クエリとは別にサーバーに送信されます。
   このことが、変数によって邪魔されることはありません。
   サーバーはステートメントのテンプレートをパース後、
   送信された値を実行時に直接使います。
   バインドされたパラメータをエスケープする必要はありません。
   サーバーがその値でクエリの文字列を直接置き換えることはないからです。
   バインドする変数の型について、サーバーにヒントを提供しなければいけません。
   これは、サーバーが適切な変換を行うために必要です。
   詳しい情報は、
   <span class="methodname"><a href="mysqli-stmt.bind-param.php" class="methodname">mysqli_stmt::bind_param()</a></span> を参照ください。
  </p>
  <p class="para">
   このように、変数とクエリを別に扱うことが、
   SQLインジェクションを防ぐ唯一のセキュリティ上の機能だと見なされることがあります。
   しかし、全ての値を適切にフォーマットしておけば、
   それと同程度のセキュリティを準備しないステートメントでも達成できます。
   正しいフォーマットとは、
   単純に値をエスケープすることではなく、
   それ以上のロジックを含むことに注意すべきです。
   よって、この手のデータベースセキュリティに対しては、
   プリペアドステートメントが単により便利で、
   エラーが起きにくいアプローチになっています。
  </p>
  <p class="para">
   <strong>クライアント側でプリペアドステートメントをエミュレートする</strong>
  </p>
  <p class="para">
   API は、クライアント側でのプリペアドステートメントのエミュレートをサポートしていません。
  </p>
  <p class="para">
   <strong>参照</strong>
  </p>
  <p class="para">
   <ul class="simplelist">
    <li><span class="methodname"><a href="mysqli.construct.php" class="methodname">mysqli::__construct()</a></span></li>
    <li><span class="methodname"><a href="mysqli.query.php" class="methodname">mysqli::query()</a></span></li>
    <li><span class="methodname"><a href="mysqli.prepare.php" class="methodname">mysqli::prepare()</a></span></li>
    <li><span class="methodname"><a href="mysqli-stmt.prepare.php" class="methodname">mysqli_stmt::prepare()</a></span></li>
    <li><span class="methodname"><a href="mysqli-stmt.execute.php" class="methodname">mysqli_stmt::execute()</a></span></li>
    <li><span class="methodname"><a href="mysqli-stmt.bind-param.php" class="methodname">mysqli_stmt::bind_param()</a></span></li>
    <li><span class="methodname"><a href="mysqli-stmt.bind-result.php" class="methodname">mysqli_stmt::bind_result()</a></span></li>
   </ul>
  </p>
 </div><?php manual_footer($setup); ?>