PDO::prepare
准备语句用于执行。
语法
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::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 |
当指定直接查询执行时 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 |
指定是否在合适时向十进制字符串添加前导零。 如已设置,此选项将启用用于设置 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 异常。 - 当准备好的语句调用包含占位符作为输出参数的存储过程时,不会引发异常,因为驱动程序无法检测输出参数。 但是,用户为输出参数提供的变量保持不变。
- 当用户使用用于输出参数的占位符创建一个准备好的语句时(也就是说,在占位符后面有一个等号,比如
- 二进制编码参数的重复占位符不起作用。