PDO::prepare

PHP ドライバーのダウンロード

実行するステートメントを準備します。

構文

PDOStatement PDO::prepare ( $statement [, array(key_pair)] )

パラメーター

$ステートメント:SQL ステートメントを含む文字列。

key_pair:属性の名前と値を含む配列。 詳細については、次の「解説」を参照してください。

戻り値

成功した場合は、PDOStatement オブジェクトを返します。 失敗した場合は、PDOException オブジェクトを、または PDO::ATTR_ERRMODE の値によっては false を返します。

解説

Microsoft SQL Server 用 Drivers for PHP では、実行されるまで準備されたステートメントを検証しません。

次の表は、使用可能な key_pair の値を一覧しています。

Key 説明
PDO::ATTR_CURSOR カーソル動作を定義します。 スクロール不可の順方向カーソル PDO::CURSOR_FWDONLY が既定値です。 PDO::CURSOR_SCROLL はスクロール可能なカーソルです。

たとえば、「 array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ) 」のように入力します。

PDO::CURSOR_SCROLL に設定すると、以下で説明するように、PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE を使用してスクロール可能なカーソルの種類を設定することができます。

PDO_SQLSRV ドライバーの結果セットとカーソルに関する詳細については、「カーソルの種類 (PDO_SQLSRV ドライバー)」を参照してください。
PDO::ATTR_EMULATE_PREPARES 既定ではこの属性は false です。この PDO::ATTR_EMULATE_PREPARES => true により変更することができます。 詳細と例については、エミュレートの準備に関するセクションを参照してください。
PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE スクロール可能なカーソルの種類を指定します。 PDO::ATTR_CURSORPDO::CURSOR_SCROLL に設定されている場合にのみ有効です。 この属性に指定可能な値については、以下を参照してください。
PDO::SQLSRV_ATTR_DECIMAL_PLACES フェッチされた通貨値の書式設定時に、小数点以下の桁数を指定します。 このオプションは PDO::SQLSRV_ATTR_FORMAT_DECIMALS が true の場合のみ機能します。 詳細については、「10 進数文字列と金額の書式設定 (PDO_SQLSRV ドライバー)」を参照してください。
PDO::SQLSRV_ATTR_DIRECT_QUERY True の場合、直接クエリの実行を指定します。 False は、準備されたステートメントの実行です。 PDO::SQLSRV_ATTR_DIRECT_QUERY に関する詳細については、「Direct Statement Execution and Prepared Statement Execution in the PDO_SQLSRV Driver」 (PDO_SQLSRV ドライバーでの直接ステートメント実行と準備されたステートメントの実行) を参照してください。
PDO::SQLSRV_ATTR_ENCODING PDO::SQLSRV_ENCODING_UTF8 (既定値)

PDO::SQLSRV_ENCODING_SYSTEM

PDO::SQLSRV_ENCODING_BINARY
PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE 日付型と時刻型を PHP DateTime オブジェクトを使用して取得するかどうかを指定します。 詳細については、「PDO_SQLSRV ドライバーを使用して日付と時刻の型を PHP DateTime オブジェクトとして取得する」を参照してください。
PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE 数値の SQL 型の列からの数値フェッチを処理します。 詳細については、「 PDO::setAttribute」を参照してください。
PDO::SQLSRV_ATTR_FORMAT_DECIMALS 該当する場合に 10 進文字列の前にゼロを追加するかどうかを指定します。 このオプションを設定すると、PDO::SQLSRV_ATTR_DECIMAL_PLACES オプションが money 型の書式設定用に有効となります。 詳細については、「10 進数文字列と金額の書式設定 (PDO_SQLSRV ドライバー)」を参照してください。
PDO::SQLSRV_ATTR_QUERY_TIMEOUT 詳細については、「 PDO::setAttribute」を参照してください。

PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL を使用する場合、PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE を使用してカーソルの種類を指定できます。 たとえば、動的カーソルを設定するには次の配列を PDO::prepare に渡します。

array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_DYNAMIC));

PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE に指定可能な値を次の表に示します。 スクロール可能なカーソルの詳細については、「カーソルの種類 (PDO_SQLSRV ドライバー)」を参照してください。

説明
PDO::SQLSRV_CURSOR_BUFFERED クライアント側の (バッファー処理された) 静的カーソルを作成します。これは、クライアント マシンのメモリ内に結果セットをバッファー処理します。
PDO::SQLSRV_CURSOR_DYNAMIC サーバー側 (バッファーなし) の動的カーソルを作成します。これは、任意の順序で行にアクセスすることができ、変更内容がデータベースに反映されます。
PDO::SQLSRV_CURSOR_KEYSET サーバー側のキーセット カーソルを作成します。 行がテーブルから削除される場合 (削除された行は、値なしで返されます)、キーセット カーソルは行の数を更新しません。
PDO::SQLSRV_CURSOR_STATIC サーバー側の静的カーソルを作成します。これは、任意の順序で行にアクセスできますが、変更内容はデータベースに反映されません。

PDO::ATTR_CURSOR => PDO::CURSOR_SCROLLPDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_STATIC を意味します。

PDOStatement オブジェクトを閉じるには、unset を呼び出します。

unset($stmt);

順方向専用の例

この例では、パラメーター マーカーと順方向専用カーソルで PDO::prepare を使用する方法を示します。

<?php
$database = "Test";
$server = "(local)";
$conn = new PDO( "sqlsrv:server=$server ; Database = $database", "", "");

$col1 = 'a';
$col2 = 'b';

$query = "insert into Table1(col1, col2) values(?, ?)";
$stmt = $conn->prepare( $query, array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY, PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 1  ) );
$stmt->execute( array( $col1, $col2 ) );
print $stmt->rowCount();
echo "\n";

$query = "insert into Table1(col1, col2) values(:col1, :col2)";
$stmt = $conn->prepare( $query, array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY, PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 1  ) );
$stmt->execute( array( ':col1' => $col1, ':col2' => $col2 ) );
print $stmt->rowCount();

unset($stmt);
?>

静的カーソルの例

この例では、サーバー側の静的カーソルで PDO::prepare を使用する方法を示します。 クライアント側カーソルの例については、「カーソルの種類 (PDO_SQLSRV ドライバー)」を参照してください。

<?php
$database = "AdventureWorks";
$server = "(local)";
$conn = new PDO( "sqlsrv:server=$server ; Database = $database", "", "");

$query = "select * from Person.ContactType";
$stmt = $conn->prepare( $query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();

echo "\n";

while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
   print "$row[Name]\n";
}
echo "\n..\n";

$row = $stmt->fetch( PDO::FETCH_BOTH, PDO::FETCH_ORI_FIRST );
print_r($row);

$row = $stmt->fetch( PDO::FETCH_ASSOC, PDO::FETCH_ORI_REL, 1 );
print "$row[Name]\n";

$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT );
print "$row[1]\n";

$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR );
print "$row[1]..\n";

$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_ABS, 0 );
print_r($row);

$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_LAST );
print_r($row);
?>

ターゲットの例

次の 2 つのスニペットでは、CHAR/VARCHAR 列のターゲットとなるデータに PDO::prepare を使用する方法を示しています。 PDO::prepare の既定のエンコードは UTF-8 なので、ユーザーはオプション PDO::SQLSRV_ENCODING_SYSTEM を使用して、暗黙的な変換を回避できます。

方法 1

$options = array(PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_SYSTEM);
$statement = $pdo->prepare(
  'SELECT *
   FROM myTable
   WHERE myVarcharColumn = :myVarcharValue',
  $options
);

$statement->bindValue(':myVarcharValue', 'my data', PDO::PARAM_STR);

方法 2

$statement = $pdo->prepare(
  'SELECT *
   FROM myTable
   WHERE myVarcharColumn = :myVarcharValue'
);
$p = 'my data';
$statement->bindParam(':myVarcharValue', $p, PDO::PARAM_STR, 0, PDO::SQLSRV_ENCODING_SYSTEM);

準備の例

この例では、PDO::ATTR_EMULATE_PREPARES を true に設定して PDO::prepare を使用する方法を示します。

<?php
$serverName = "yourservername";
$username = "yourusername";
$password = "yourpassword";
$database = "tempdb";
$conn = new PDO("sqlsrv:server = $serverName; Database = $database", $username, $password);

$pdo_options = array();
$pdo_options[PDO::ATTR_EMULATE_PREPARES] = true;
$pdo_options[PDO::SQLSRV_ATTR_ENCODING] = PDO::SQLSRV_ENCODING_UTF8;

$stmt = $conn->prepare("CREATE TABLE TEST([id] [int] IDENTITY(1,1) NOT NULL,
                                          [name] nvarchar(max))",
                                          $pdo_options);
$stmt->execute();

$prefix = '가각';
$name = '가각ácasa';
$name2 = '가각sample2';

$stmt = $conn->prepare("INSERT INTO TEST(name) VALUES(:p0)", $pdo_options);
$stmt->execute(['p0' => $name]);
unset($stmt);

$stmt = $conn->prepare("SELECT * FROM TEST WHERE NAME LIKE :p0", $pdo_options);
$stmt->execute(['p0' => "$prefix%"]);
foreach ($stmt as $row) {
    echo "\n" . 'FOUND: ' . $row['name'];
}

unset($stmt);
unset($conn);
?>

PDO_SQLSRV ドライバーの内部で、すべてのプレースホルダーが PDOStatement::bindParam() でバインドされたパラメーターで置き換えられます。 そのため、プレースホルダーのない SQL クエリ文字列がサーバーに送信されます。 次の例について考えてみます。

$statement = $PDO->prepare("INSERT into Customers (CustomerName, ContactName) VALUES (:cus_name, :con_name)");
$statement->bindParam(:cus_name, "Cardinal");
$statement->bindParam(:con_name, "Tom B. Erichsen");
$statement->execute();

PDO::ATTR_EMULATE_PREPARES が false に設定されている場合 (既定のケース)、データベースに送信されるデータは次のとおりです。

"INSERT into Customers (CustomerName, ContactName) VALUES (:cus_name, :con_name)"
Information on :cus_name parameter
Information on :con_name parameter

サーバーでは、パラメーターのバインド用のパラメーター化クエリ機能を使用してクエリが実行されます。 一方で、PDO::ATTR_EMULATE_PREPARES が true に設定されている場合、サーバーに送信されるクエリは基本的に次のとおりです。

"INSERT into Customers (CustomerName, ContactName) VALUES ('Cardinal', 'Tom B. Erichsen')"

PDO::ATTR_EMULATE_PREPARES を true に設定すると、SQL Server のいくつかの制限事項をバイパスすることができます。 たとえば、SQL Server では名前付きまたは位置パラメーターは一部の Transact-SQL 句でサポートされていません。 さらに、SQL Server には、2100 個のパラメーターのバインドの制限があります。

Note

emulate prepare が true に設定されている場合、パラメーター化クエリのセキュリティは有効ではありません。 そのため、アプリケーションでは、パラメーターにバインドされたデータに、悪意のある Transact-SQL コードが含まれていないことを確認する必要があります。

エンコード

別のエンコーディング (UTF-8 やバイナリなど) でパラメーターをバインドしたい場合、PHP スクリプトにエンコーディングを明確に指定する必要があります。

PDO_SQLSRV ドライバーでは最初に PDO::bindParam() に指定されたエンコーディングがチェックされます (たとえば、$statement->bindParam(:cus_name, "Cardinal", PDO::PARAM_STR, 10, PDO::SQLSRV_ENCODING_UTF8))。

見つからない場合、PDO::prepare() または PDOStatement::setAttribute() にエンコーディングが設定されているかどうかドライバーによりチェックされます。 それ以外の場合、ドライバーでは PDO::__construct() または PDO::setAttribute() に指定されたエンコーディングが使用されます。

さらに、バージョン5.8.0 以降では、PDO::ATTR_EMULATE_PREPARES を true に設定して PDO::p repare を使用する場合には、N プレフィックスが確実に使用されるように、ユーザーは PHP 7.2 で導入された拡張文字列型を使用できます。 以下のスニペットでは、さまざまな代替方法を示しています。

注意

既定では、emulate prepare が false に設定されます。この場合、拡張された PDO 文字列定数は無視されます。

バインド時にドライバー オプション PDO::SQLSRV_ENCODING_UTF8 を使用する

$p = '가각';
$sql = 'SELECT :value';
$options = array(PDO::ATTR_EMULATE_PREPARES => true);
$stmt = $conn->prepare($sql, $options);
$stmt->bindParam(':value', $p, PDO::PARAM_STR, 0, PDO::SQLSRV_ENCODING_UTF8);
$stmt->execute();

PDO::SQLSRV_ATTR_ENCODING 属性を使用する

$p = '가각';
$sql = 'SELECT :value';
$options = array(PDO::ATTR_EMULATE_PREPARES => true, PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8);
$stmt = $conn->prepare($sql, $options);
$stmt->execute([':value' => $p]);

PDO 定数 PDO::PARAM_STR_NATL を使用する

$p = '가각';
$sql = 'SELECT :value';
$options = array(PDO::ATTR_EMULATE_PREPARES => true);
$stmt = $conn->prepare($sql, $options);
$stmt->bindParam(':value', $p, PDO::PARAM_STR | PDO::PARAM_STR_NATL);
$stmt->execute();

既定の文字列パラメーターの型 PDO::P ARAM_STR_NATL を設定する

$conn->setAttribute(PDO::ATTR_DEFAULT_STR_PARAM, PDO::PARAM_STR_NATL);
$p = '가각';
$sql = 'SELECT :value';
$options = array(PDO::ATTR_EMULATE_PREPARES => true);
$stmt = $conn->prepare($sql, $options);
$stmt->execute([':value' => $p]);

制限事項

ご覧のように、バインディングはドライバーによって内部的に行われます。 有効なクエリが実行のためにパラメーターなしでサーバーに送信されます。 通常のケースと比較すると、パラメーター化クエリ機能が使用されていない場合にいくつかの制限事項が発生します。

  • PDO::PARAM_INPUT_OUTPUT としてバインドされたパラメーターの場合は機能しません。
    • ユーザーが PDO::bindParam()PDO::PARAM_INPUT_OUTPUT を指定すると、PDO 例外がスローされます。
  • 出力パラメーターとしてバインドされたパラメーターの場合は機能しません。
    • ユーザーが準備されたステートメントを出力パラメーター用のプレースホルダーを使用して作成した場合 (つまり、SELECT ? = COUNT(*) FROM Table1 のようにプレースホルダーのすぐ後に等号が指定されている場合)、PDO 例外がスローされます。
    • 準備されたステートメントにより、出力パラメーター用の引数としてプレースホルダーを使用してストアド プロシージャが呼び出された場合、ドライバーでは出力パラメーターを検出できないため、例外はスローされません。 一方で、ユーザーが出力パラメーター用に指定した変数は変更されません。
  • バイナリでエンコードされたパラメーター用にプレースホルダーが重複して指定されている場合、機能しません。

参照

PDO クラス

PDO