次の方法で共有


PDO::prepare

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

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

構文

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

パラメーター

$statement

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

key_pair

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

戻り値

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

解説

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

次の表は、使用可能な 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 ドライバーの結果セットとカーソルの詳細については、「Cursor 型 (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 を意味します。

unsetを呼び出すと、PDOStatement オブジェクトを閉じます。

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 には 2,100 個のパラメーターをバインドする制限があります。

Note

エミュレートの準備を 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 を使用する場合、ユーザーは PHP 7.2 で導入された拡張文字列型を使用して、N プレフィックスが確実に使用されるようにすることができます。 次のスニペットは、さまざまな代替手段を示しています。

Note

既定では、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::P ARAM_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 例外がスローされます。
    • 準備されたステートメントが、出力パラメーターの引数としてプレースホルダーを持つストアド プロシージャを呼び出す場合、ドライバーが出力パラメーターを検出できないため、例外はスローされません。 ただし、ユーザーが出力パラメーターに指定した変数は変更されません。
  • バイナリ でエンコードされたパラメーターのプレースホルダーが重複しても機能しません。