PDO::prepare

Скачать драйвер PHP

Подготавливает инструкцию для выполнения.

Синтаксис

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.
    • Если подготовленная инструкция вызывает хранимую процедуру с заполнителем в качестве аргумента для выходного параметра, исключение не создается, так как драйвер не может обнаружить такой выходной параметр. Но при этом переменная, предоставленная пользователем для выходного параметра, не изменится.
  • Повторяющиеся заполнители для параметра в двоичной кодировке работать не будут.

См. также:

Класс PDO

PDO