PDO::prepare

下载 PHP 驱动程序

准备语句用于执行。

语法

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

参数

$语句

包含 SQL 语句的字符串。

key_pair

包含属性名称和值的数组。 有关详细信息,请参阅备注部分。

返回值

返回 PDOStatement 成功时的对象。 失败时,返回对象 PDOException 或 false,具体取决于值 PDO::ATTR_ERRMODE

注解

Microsoft Drivers for PHP for SQL Server 在执行之前不会评估准备好的语句。

下表列出可能的 key_pair 值。

说明
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 指定设置提取的 Money 值格式时的小数位数。 仅当 PDO::SQLSRV_ATTR_FORMAT_DECIMALS 为 true 时此选项才起作用。 有关详细信息,请参阅设置十进制字符串和 Money 值格式(PDO_SQLSRV 驱动程序)
PDO::SQLSRV_ATTR_DIRECT_QUERY 当指定直接查询执行时 TrueFalse 表示准备的语句执行。 有关 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 指定是否在合适时向十进制字符串添加前导零。 如已设置,此选项将启用用于设置 Money 类型格式的 PDO::SQLSRV_ATTR_DECIMAL_PLACES 选项。 有关详细信息,请参阅设置十进制字符串和 Money 值格式(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);
?>

目标示例

以下两个代码片段演示如何PDO::prepare用于针对 char / varchar 列的数据。 由于默认编码 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);

Prepare 示例

此示例演示如何将 PDO::prepare 设置为 true 的 PDO::ATTR_EMULATE_PREPARES 结合使用。

<?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首先检查在 (例如, $statement->bindParam(:cus_name, "Cardinal", PDO::PARAM_STR, 10, PDO::SQLSRV_ENCODING_UTF8)) 中指定的PDO::bindParam()编码。

如果找不到,则驱动程序会检查是否在 PDO::prepare()PDOStatement::setAttribute() 中设置了任何编码。 否则,驱动程序使用在或 PDO::setAttribute().. 中PDO::__construct()指定的编码。

此外,从版本 5.8.0 开始,使用设置为 true 的 PDO::p repare PDO::ATTR_EMULATE_PREPARES 时,用户可以使用 PHP 7.2 中引入的扩展字符串类型来确保 N 使用前缀。 以下代码片段显示各种替代方法。

注意

默认情况下,模拟准备设置为 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 异常。
    • 当准备好的语句调用包含占位符作为输出参数的存储过程时,不会引发异常,因为驱动程序无法检测输出参数。 但是,用户为输出参数提供的变量保持不变。
  • 二进制编码参数的重复占位符不起作用。