PDO::prepare

Baixar o driver PHP

Prepara uma instrução para execução.

Sintaxe

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

Parâmetros

$instrução

uma cadeia de caracteres que contém a instrução SQL.

key_pair

uma matriz que contém um nome e valor de atributo. Para obter mais informações, consulte a seção Comentários.

Valor retornado

Retorna um PDOStatement objeto em caso de êxito. Em caso de falha, retorna um PDOException objeto ou false, dependendo do valor de PDO::ATTR_ERRMODE.

Comentários

Os Drivers da Microsoft para PHP para SQL Server não avaliam instruções preparadas até a execução.

A tabela a seguir mostra os valores possíveis de key_pair.

Chave Descrição
PDO::ATTR_CURSOR Especifica o comportamento do cursor. O padrão é PDO::CURSOR_FWDONLY, um cursor de avanço que não é de rolagem. PDO::CURSOR_SCROLL é um cursor de rolagem.

Por exemplo, array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ).

Quando definido como PDO::CURSOR_SCROLL, você pode usar PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE para definir o tipo de cursor rolável, que é descrito posteriormente neste artigo.

Consulte Tipos de cursor (driver PDO_SQLSRV) para obter mais informações sobre conjuntos de resultados e cursores no PDO_SQLSRV driver.
PDO::ATTR_EMULATE_PREPARES Por padrão, esse atributo é false, e pode ser alterado usando o seguinte: PDO::ATTR_EMULATE_PREPARES => true. Confira Emulate Prepare para saber mais e ver exemplos.
PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE Especifica o tipo de cursor de rolagem. Válido somente quando PDO::ATTR_CURSOR está definido como PDO::CURSOR_SCROLL. Consulte mais adiante neste artigo os valores que esse atributo pode assumir.
PDO::SQLSRV_ATTR_DECIMAL_PLACES Especifica o número de casas decimais ao formatar valores monetários buscados. Essa opção só funciona quando PDO::SQLSRV_ATTR_FORMAT_DECIMALS é true. Para saber mais, confira Formatação de cadeias de caracteres decimais e valores monetários (driver PDO_SQLSRV) .
PDO::SQLSRV_ATTR_DIRECT_QUERY Quando True, especifica a execução direta da consulta. False significa execução de instrução preparada. Para saber mais sobre PDO::SQLSRV_ATTR_DIRECT_QUERY, confira Execução de instrução direta e execução de instrução preparada no driver PDO_SQLSRV.
PDO::SQLSRV_ATTR_ENCODING PDO::SQLSRV_ENCODING_UTF8 (padrão)
PDO::SQLSRV_ENCODING_SYSTEM
PDO::SQLSRV_ENCODING_BINARY
PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE Especifica quando recuperar tipos de data e hora como objetos de DateTime PHP. Para obter mais informações, confira Como recuperar tipos de data e hora como objetos DateTime PHP usando o driver PDO_SQLSRV.
PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE Lida com buscas numéricas de colunas com tipos SQL numéricos. Para obter mais informações, consulte PDO::setAttribute.
PDO::SQLSRV_ATTR_FORMAT_DECIMALS Especifica quando é apropriado adicionar zeros à esquerda em cadeias de caracteres decimais. Se definida, essa opção habilita a opção PDO::SQLSRV_ATTR_DECIMAL_PLACES para formatação de tipos de moeda. Para saber mais, confira Formatação de cadeias de caracteres decimais e valores monetários (driver PDO_SQLSRV) .
PDO::SQLSRV_ATTR_QUERY_TIMEOUT Para obter mais informações, consulte PDO::setAttribute.

Ao usar PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, use PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE para especificar o tipo de cursor. Por exemplo, passe a seguinte matriz para PDO::prepare para definir um cursor dinâmico:

array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_DYNAMIC));

A tabela a seguir mostra os valores possíveis para PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE. Para saber mais sobre os cursores de rolagem, confira Tipos de cursor (PDO_SQLSRV Driver).

Valor Descrição
PDO::SQLSRV_CURSOR_BUFFERED Cria um cursor estático do lado do cliente (em buffer), que armazena em buffer o conjunto de resultados na memória do computador do cliente.
PDO::SQLSRV_CURSOR_DYNAMIC Cria um cursor dinâmico do lado do servidor (sem buffer), que permite acessar linhas em qualquer ordem e refletir as alterações no banco de dados.
PDO::SQLSRV_CURSOR_KEYSET Cria um cursor de conjunto de chaves do lado do servidor. Um cursor de conjunto de chaves não atualiza a contagem de linhas se uma linha for excluída da tabela (uma linha excluída é retornada sem valores).
PDO::SQLSRV_CURSOR_STATIC Cria um cursor estático do lado do servidor, que permite acessar linhas em qualquer ordem, mas não reflete as alterações no banco de dados.

PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL implica PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_STATIC.

Você pode fechar um PDOStatement objeto chamando unset:

unset($stmt);

Exemplo de somente avanço

Este exemplo mostra como usar PDO::prepare com marcadores de parâmetro e um cursor somente para frente.

<?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);
?>

Exemplo de cursor estático

Este exemplo mostra como usar PDO::prepare com um cursor estático do lado do servidor. Para ver um exemplo que mostra um cursor do lado do cliente, confira Tipos de cursor (PDO_SQLSRV Driver).

<?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);
?>

Exemplo direcionado

Os dois snippets a seguir mostram como usar PDO::prepare com dados direcionados para colunas char / varchar. Como a codificação padrão é PDO::prepare UTF-8, o usuário pode usar a opção PDO::SQLSRV_ENCODING_SYSTEM para evitar conversões implícitas.

Opção 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);

Opção 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);

Exemplo com prepare

Este exemplo mostra como usar o método PDO::prepare com PDO::ATTR_EMULATE_PREPARES definido como 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);
?>

O PDO_SQLSRV driver substitui internamente todos os espaços reservados pelos parâmetros associados a PDOStatement::bindParam(). Portanto, uma cadeia de caracteres de consulta SQL sem espaços reservados é enviada ao servidor. Considere este exemplo:

$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();

Com PDO::ATTR_EMULATE_PREPARES definido como false (o caso padrão), os dados enviados para o banco de dados são:

"INSERT into Customers (CustomerName, ContactName) VALUES (:cus_name, :con_name)"
Information on :cus_name parameter
Information on :con_name parameter

O servidor executa a consulta usando seu recurso de consulta parametrizada para parâmetros de associação. Por outro lado, com PDO::ATTR_EMULATE_PREPARES definido como true, a consulta enviada ao servidor é essencialmente:

"INSERT into Customers (CustomerName, ContactName) VALUES ('Cardinal', 'Tom B. Erichsen')"

Definir PDO::ATTR_EMULATE_PREPARES como true pode ignorar algumas restrições no SQL Server. Por exemplo, o SQL Server não dá suporte a parâmetros nomeados ou posicionais em algumas cláusulas Transact-SQL. Além disso, o SQL Server tem um limite de 2.100 parâmetros.

Observação

Com emulate prepara definido como true, a segurança de consultas parametrizadas não está em vigor. Portanto, seu aplicativo deve garantir que os dados associados aos parâmetros não contenham código Transact-SQL mal-intencionado.

Codificação

Se o usuário deseja associar parâmetros com diferentes codificações (por exemplo, UTF-8 ou binária), ele deve especificar claramente a codificação no script PHP.

O PDO_SQLSRV driver primeiro verifica a codificação especificada em PDO::bindParam() (por exemplo, $statement->bindParam(:cus_name, "Cardinal", PDO::PARAM_STR, 10, PDO::SQLSRV_ENCODING_UTF8)).

Se não encontrado, o driver verifica se alguma codificação está definida em PDO::prepare() ou PDOStatement::setAttribute(). Caso contrário, o driver usará a codificação especificada em PDO::__construct() ou PDO::setAttribute().

Além disso, a partir da versão 5.8.0, ao usar PDO::p repare com PDO::ATTR_EMULATE_PREPARES set to true, o usuário pode usar os tipos de string estendida introduzidos no PHP 7.2 para garantir que o prefixo N seja usado. Os snippets a seguir exibem várias alternativas.

Observação

Por padrão, Emulate Prepare é definido como false. Nesse caso, as constantes de cadeia de caracteres PDO estendidas serão ignoradas.

Usar a opção de driver PDO::SQLSRV_ENCODING_UTF8 ao associar

$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();

Use o atributo 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]);

Use a constante 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();

Defina o tipo de parâmetro de string padrão 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]);

Limitações

Como você pode ver, a associação é feita internamente pelo driver. Uma consulta válida é enviada ao servidor para execução sem nenhum parâmetro. Em comparação com o caso normal, algumas limitações resultam quando o recurso de consulta parametrizada não está em uso.

  • Não funciona para parâmetros vinculados como PDO::PARAM_INPUT_OUTPUT.
    • Quando o usuário especifica PDO::PARAM_INPUT_OUTPUT em PDO::bindParam(), ocorre uma exceção de PDO.
  • Ele não funciona para parâmetros associados como parâmetros de saída.
    • Quando o usuário cria uma instrução preparada com espaços reservados que servem para parâmetros de saída (ou seja, ter um sinal de igual imediatamente após um espaço reservado, como SELECT ? = COUNT(*) FROM Table1), ocorre uma exceção de PDO.
    • Quando uma instrução preparada invoca um procedimento armazenado com um espaço reservado como argumento para um parâmetro de saída, nenhuma exceção é gerada porque o driver não pode detectar o parâmetro de saída. No entanto, a variável que o usuário fornece para o parâmetro de saída permanece inalterada.
  • Espaços reservados duplicados para um parâmetro codificado binário não funcionam.