PDO::prepare
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
emPDO::bindParam()
, ocorre uma exceção de PDO.
- Quando o usuário especifica
- 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.
- 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
- Espaços reservados duplicados para um parâmetro codificado binário não funcionam.