PDO::prepare
Подготавливает инструкцию для выполнения.
Синтаксис
PDOStatement PDO::prepare ( $statement [, array(key_pair)] )
Параметры
$statement: Строка, содержащая инструкцию SQL.
key_pair: Массив, содержащий имя и значение атрибута. Дополнительные сведения см. в разделе "Примечания".
Возвращаемое значение
В случае успеха возвращает объект PDOStatement. В случае сбоя возвращает объект PDOException или значение false в зависимости от значения PDO::ATTR_ERRMODE
.
Remarks
Драйверы Microsoft SQL Server для PHP Не оценивает подготовленную инструкцию до самого выполнения.
Возможные значения 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 | Указывает число десятичных знаков при форматировании полученных денежных значений. Этот параметр работает только в том случае, если 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. Дополнительные сведения см. в разделе Как извлечь типы даты и времени в виде объектов даты и времени PHP с помощью драйвера PDO_SQLSRV. |
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).
Значение | Описание |
---|---|
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 . |
Объект PDOStatement можно закрыть, вызвав unset
.
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);
Пример подготовки
В этом примере показано, как использовать PDO::prepare с PDO::ATTR_EMULATE_PREPARES
, имеющим значение true.
<?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 имеет ограничение в 2100 параметров привязки.
Примечание
Если параметр подготовки эмуляции имеет значение 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::prepare со значением true для параметра 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::PARAM_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::PARAM_INPUT_OUTPUT
вPDO::bindParam()
, создается исключение PDO.
- Если пользователь указал
- Он не работает для параметров, привязка которых настроена как внешний параметр.
- Когда пользователь создает подготовленную инструкцию с заполнителями для выходных параметров (то есть со знаком равенства сразу же после заполнителя, например
SELECT ? = COUNT(*) FROM Table1
), создается исключение PDO. - Если подготовленная инструкция вызывает хранимую процедуру с заполнителем в качестве аргумента для выходного параметра, исключение не создается, так как драйвер не может обнаружить такой выходной параметр. Но при этом переменная, предоставленная пользователем для выходного параметра, не изменится.
- Когда пользователь создает подготовленную инструкцию с заполнителями для выходных параметров (то есть со знаком равенства сразу же после заполнителя, например
- Повторяющиеся заполнители для параметра в двоичной кодировке работать не будут.
См. также:
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по