PDO::prepare
進行執行陳述式的準備。
語法
PDOStatement PDO::prepare ( $statement [ , array(key_pair) ] )
參數
$陳述式
包含 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 結果集和數據指標的詳細資訊,請參閱數據指標類型(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 時才能運作。 如需詳細資訊,請參閱將十進位字串及貨幣值格式化 (PDO_SQLSRV 驅動程式)。 |
PDO::SQLSRV_ATTR_DIRECT_QUERY |
當 時 True ,指定直接查詢執行。 False 表示備妥的語句執行。 如需 PDO::SQLSRV_ATTR_DIRECT_QUERY 的詳細資訊,請參閱 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 |
指定是否要在適當時於十進位字串中新增前置零。 如果設定,此選項就會啟用 PDO::SQLSRV_ATTR_DECIMAL_PLACES 選項來將貨幣類型格式化。 如需詳細資訊,請參閱將十進位字串及貨幣值格式化 (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 驅動程式)。
值 | Description |
---|---|
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);
?>
目標範例
下列兩個代碼段示範如何搭配以 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);
準備範例
此範例示範如何搭配設定為 true 的 PDO::ATTR_EMULATE_PREPARES
來使用 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 個參數的限制。
注意
當模擬準備設定為 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::setAttribute()
中指定的PDO::__construct()
編碼方式。
此外,從 5.8.0 版開始,使用 PDO::p repare 設定 PDO::ATTR_EMULATE_PREPARES
為 true 時,使用者可以使用 PHP 7.2 中引進的擴充字元串類型,以確保 N
使用前置詞。 下列代碼段會顯示各種替代方案。
注意
根據預設,emulate prepares 會設定為 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 例外狀況。 - 當備妥的語句使用佔位元作為輸出參數的自變數叫用預存程式時,不會擲回例外狀況,因為驅動程式無法偵測輸出參數。 不過,用戶為輸出參數提供的變數保持不變。
- 當使用者搭配用來作為輸出參數的預留位置 (也就是,在預留位置後面緊接著等號,例如
- 二進位編碼參數的重複佔位元無法運作。