分享方式:


PDO::prepare

下載 PHP 驅動程式

進行執行陳述式的準備。

語法

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 例外狀況。
    • 當備妥的語句使用佔位元作為輸出參數的自變數叫用預存程式時,不會擲回例外狀況,因為驅動程式無法偵測輸出參數。 不過,用戶為輸出參數提供的變數保持不變。
  • 二進位編碼參數的重複佔位元無法運作。