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