Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Ambos os drivers podem executar uma instrução uma vez ou preparar uma instrução para execução repetida. Use parâmetros para os valores fornecidos pelos usuários, mesmo quando você executa uma consulta apenas uma vez.
Escolha a API de execução separadamente de como você busca os resultados. Preparar uma consulta não recupera suas linhas, e armazenar um resultado em buffer não faz com que a consulta seja parametrizada. Os exemplos a seguir preparam uma consulta somente leitura uma vez, executam-na duas vezes com valores diferentes e consomem cada resultado antes da próxima execução.
| Estilo de execução | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Execute uma consulta uma vez, sem parâmetros | sqlsrv_query | PDO::query para resultados, ou PDO::exec para contagens de linhas afetadas |
| Execute uma consulta uma vez, com parâmetros | sqlsrv_query($conn, $sql, $params) |
PDO::prepare() seguido por PDOStatement::execute() |
| Prepare uma vez, execute repetidamente com diferentes parâmetros | sqlsrv_prepare + sqlsrv_execute | PDO::prepare + PDOStatement::execute |
sqlsrv_query() prepara e executa em uma única chamada e retorna um recurso de declaração.
sqlsrv_prepare() retorna um recurso de instrução sem executá-lo; chame sqlsrv_execute() para cada execução. O query() PDO executa e retorna PDOStatement, enquanto exec() retorna uma contagem de linhas afetadas em vez de um objeto resultado. Uma chamada exec() bem-sucedida pode retornar 0, então compare um retorno de falha com === false, não if (!$count).
PDO::query() não aceita um array de valores de parâmetros. Seus argumentos opcionais configuram a obtenção. Para consultas PDO_SQLSRV parametrizadas, use prepare() e execute().
Preparar uma vez permite que você reutilize um manipulador de instrução com valores diferentes. Isso não garante que o servidor nunca recompile seu plano de execução. PDO_SQLSRV usa execução preparada por padrão, incluindo para PDO::query(); seu atributo de consulta direta controla essa escolha separada.
Prepare uma vez e execute repetidamente
São programas separados e completos de linha de comando. Instale e carregue a extensão selecionada, e defina SQL_SERVER, SQL_DATABASE, SQL_USER, e SQL_PASSWORD no ambiente de processo PHP. Use um banco de dados de teste SQL Server e um certificado de servidor confiável pelo cliente. Para a configuração do ambiente e alternativas sem senha, veja Conectando ao servidor.
Armazene o nome real do banco de dados, nome de usuário e senha nas variáveis de ambiente. Ambos os programas escapam desses valores uma vez dobrando as chaves de fechamento e encerrando cada valor entre chaves, conforme exigido pelo tratamento de conexão no estilo ODBC do driver PHP. Escapar valores de conexão é separado de vincular parâmetros de consulta.
Os programas executam uma consulta Transact-SQL (T-SQL) em duas linhas inline sem criar uma tabela ou alterar dados. Salve cada programa em seu próprio .php arquivo e execute com php <file>. Não é necessário um banco de dados de exemplo.
SQLSRV
Passe $productId por referência com &$productId. Cada um sqlsrv_execute() então usa seu valor atual.
SQLSRV_FETCH_ASSOC retorna um array indexado pelo nome da coluna. Um null resultado significa que não há mais linhas; false indica um erro.
<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
$value = getenv($name);
if ($value === false || $value === '') {
throw new RuntimeException("Set $name before running this example.");
}
$config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
$config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}
$conn = sqlsrv_connect($config['SQL_SERVER'], [
'Database' => $config['SQL_DATABASE'],
'UID' => $config['SQL_USER'],
'PWD' => $config['SQL_PASSWORD'],
'Encrypt' => true,
'TrustServerCertificate' => false,
'LoginTimeout' => 30,
'CharacterSet' => 'UTF-8',
]);
if ($conn === false) {
throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
$sql = "SELECT Name FROM (VALUES (1, 'Bike'), (2, 'Helmet')) AS Product(ProductId, Name) WHERE ProductId = ?";
$productId = 1;
$stmt = null;
try {
$stmt = sqlsrv_prepare($conn, $sql, [&$productId], ['QueryTimeout' => 30]);
if ($stmt === false) {
throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
foreach ([1 => 'Bike', 2 => 'Helmet'] as $productId => $expected) {
if (!sqlsrv_execute($stmt)) {
throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
$names = [];
while (($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) !== null) {
if ($row === false) {
throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
$names[] = $row['Name'];
}
if ($names !== [$expected]) {
throw new RuntimeException('Expected exactly one matching product.');
}
echo $names[0], PHP_EOL;
}
} finally {
if (is_resource($stmt)) {
sqlsrv_free_stmt($stmt);
}
sqlsrv_close($conn);
}
PDO_SQLSRV
Vincule $productId uma vez com bindParam(). Cada execute() lê seu valor atual.
PDO::PARAM_INT especifica o tipo de ligação PHP/PDO do parâmetro; ele não controla o tipo PHP das colunas obtidas do resultado. Defina o modo de exceção para que um erro de banco de dados interrompa a execução, em vez de ser confundido com um resultado vazio.
<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
$value = getenv($name);
if ($value === false || $value === '') {
throw new RuntimeException("Set $name before running this example.");
}
$config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
$config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}
$server = $config['SQL_SERVER'];
$database = $config['SQL_DATABASE'];
$pdo = new PDO(
"sqlsrv:Server=$server;Database=$database;Encrypt=true;"
. "TrustServerCertificate=false;LoginTimeout=30",
$config['SQL_USER'],
$config['SQL_PASSWORD'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8,
]
);
$sql = "SELECT Name FROM (VALUES (1, 'Bike'), (2, 'Helmet')) AS Product(ProductId, Name) WHERE ProductId = ?";
$stmt = null;
try {
$stmt = $pdo->prepare($sql, [PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 30]);
$productId = 1;
$stmt->bindParam(1, $productId, PDO::PARAM_INT);
foreach ([1 => 'Bike', 2 => 'Helmet'] as $productId => $expected) {
$stmt->execute();
$names = $stmt->fetchAll(PDO::FETCH_COLUMN);
if ($names !== [$expected]) {
throw new RuntimeException('Expected exactly one matching product.');
}
echo $names[0], PHP_EOL;
$stmt->closeCursor();
}
} finally {
$stmt = null;
$pdo = null;
}
Cada exemplo imprime:
Bike
Helmet
Valores em um array passados para PDO's execute() são tratados como PDO::PARAM_STR. Quando SQL requer um parâmetro inteiro, como uma contagem parametrizada TOP , chame bindValue() com PDO::PARAM_INT e depois chame execute() sem um array.
Vincule valores sem alterar a consulta
Um marcador de parâmetro representa um valor, não um nome de tabela, nome de coluna, palavra-chave ou direção de ordenação. Não coloque aspas ao redor de ?. Para um identificador dinâmico ou ASC/DESC, selecione de uma lista de permissões controlada por aplicativos em vez de concatenar texto não confiável. Para uma IN lista, forneça um marcador por valor.
| Requirement | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Vincular valores para uma execução | Passe o array de parâmetros para sqlsrv_query(). |
Passe um array para execute() depois de prepare(), ou atribua valores primeiro. |
| Reutilizar o valor atual de uma variável | Inclua &$variable no array fornecido a sqlsrv_prepare(). |
Chame bindParam() com a variável, depois execute() sem um array. PHP passa a variável por referência; não adicione & no local da chamada. |
| Vincule um valor no momento da vinculação | Use um valor no array de parâmetros para a execução. | Chame bindValue(); alterações posteriores na variável original não alteram esse valor vinculado. |
| Especifique uma entrada inteira | Use um descritor de parâmetro com SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT, e SQLSRV_SQLTYPE_INT quando um tipo explícito for necessário. |
Vincule com PDO::PARAM_INT. Os índices posicionais bindParam() e bindValue() começam em 1, não 0em . |
Enviar SQL NULL |
Vincule PHP null, com um tipo SQL explícito quando exigido pela operação. |
Vincule com PDO::PARAM_NULL. |
| Receber parâmetros de saída | Use uma variável referenciada com SQLSRV_PARAM_OUT ou SQLSRV_PARAM_INOUT. |
Use bindParam() com PDO::PARAM_INPUT_OUTPUT e o tipo e comprimento necessários. |
Mantenha as variáveis referenciadas ativas ao executar a declaração preparada. O programa SQLSRV altera a variável limitada em vez de substituir o array de parâmetros. O programa PDO chama execute() deliberadamente sem array após a vinculação; não misture esse padrão com execução baseada em array.
Os valores de saída dos procedimentos armazenados exigem seu próprio manuseio, incluindo a conclusão dos resultados do procedimento. Não infira comportamento de parâmetros de saída a partir desses exemplos apenas de entrada. Para mais informações, veja Uso de parâmetros direcionais.
Configurar execução e comportamento de busca
| Setting | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Tempo de execução |
QueryTimeout no array de opções de instrução. |
PDO::SQLSRV_ATTR_QUERY_TIMEOUT Na conexão ou declaração. |
| Chaves de resultado nomeadas |
SQLSRV_FETCH_ASSOC passado para sqlsrv_fetch_array(). |
PDO::FETCH_ASSOC passado para um método de fetch ou definido como modo de fetch padrão da conexão. |
| Resultados apenas para atacantes | Cursor padrão; buscar na ordem. | Cursor padrão; buscar na ordem. |
| Resultados com buffer de cliente |
Scrollable => SQLSRV_CURSOR_CLIENT_BUFFERED. |
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL com PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED. |
| Execução direta versus preparada | Sem atributo de consulta direta do PDO. Escolha a chamada combinada sqlsrv_query() ou o par explícito preparar/executar. |
PDO::SQLSRV_ATTR_DIRECT_QUERY seleciona execução direta versus a execução preparada padrão do driver. |
| Emulação de parâmetro | Sem atributo de emulação de PDO. |
PDO::ATTR_EMULATE_PREPARES é separado do atributo de consulta direta. Não use isso como substituto para encadernar os tipos corretos. |
Os exemplos retornam resultados pequenos.
fetchAll() carrega cada linha na memória PHP; usa um loop de busca para um resultado grande. Uma consulta que não retorna correspondências não é um erro de execução. O SQLSRV reporta o final do resultado como null de sqlsrv_fetch_array(); O PDO reporta como false de fetch(). Um SQL NULL dentro de uma linha recuperada continua sendo PHP null.
Não use a SELECTcontagem de linhas como seu único teste de sucesso. Cursores apenas para frente não oferecem as mesmas capacidades de contagem de linhas que cursores em buffer ou roláveis. Busque e conte as linhas que você precisa, ou use uma consulta separada COUNT . Para opções e limitações específicas de cursor, veja Especificar um tipo de cursor e selecionar linhas.
Tratar falhas e finalizar resultados
Verifique SQLSRV prepare, execute e fetch separadamente. Um prepare bem-sucedido não prova que a execução será bem-sucedida: o servidor pode rejeitar valores de parâmetros, permissões ou a instrução no momento da execução. Capture sqlsrv_errors() imediatamente quando uma operação retornar false. O SQLSRV trata muitos avisos como erros por padrão, então inspecione a coleção completa.
Para PDO, falhas de conexão e erros de banco de dados no modo exceção lançam PDOException. Inspecione suas informações de SQLSTATE e erro do driver em diagnósticos de aplicação protegida; não retorne texto de exceção ou credenciais em uma resposta HTTP.
prepare() Ter sucesso não é prova de que a declaração já foi executada.
| Sintoma | Action |
|---|---|
| Toda execução usa o primeiro valor | Para SQLSRV, vincule uma variável por referência. Para PDO, use bindParam() para uma variável que muda ou chame bindValue() para cada novo valor. |
Um parâmetro numérico é rejeitado, como um valor de TOP contagem |
Vincule explicitamente o tipo inteiro necessário. O PDO execute([$value]) usa parâmetros de string mesmo que o valor PHP seja um inteiro. |
| Um segundo comando reporta resultados pendentes | Consuma os resultados ou libere-os antes de reutilizar a conexão. Para PDO, use closeCursor() quando não precisar do resultado restante. |
| Os parâmetros esperados de saída não mudaram | Complete todos os resultados do procedimento e verifique a direção dos parâmetros, o tipo PHP e o comprimento do buffer de saída. |
| O uso de memória cresce com o tamanho do resultado | Substitua fetchAll() ou buffering do cliente desnecessário por busca sequencial. |
Os exemplos desalocam suas instruções e liberam suas conexões em finally. Eles não iniciam uma transação. Use uma transação explícita quando múltiplas escritas devem ou fazer commit juntas ou todas ser revertidas. Reutilizar uma instrução preparada não agrupa as gravações em uma transação.
Diferenças entre destino e implementação
As APIs prepare/execute e as regras de referência do PHP pertencem às extensões e ao PHP/PDO. O destino SQL decide quais instruções e tipos de T-SQL são suportados, e o ODBC realiza a comunicação subjacente. Preparar uma vez pode reduzir o trabalho repetido, mas não garante um plano específico de execução do servidor ou ganho de desempenho.
Os padrões de ligação de entrada se aplicam ao SQL Server, Banco de Dados SQL do Azure, Instância Gerenciada de SQL do Azure, Azure Synapse Analytics, banco de dados SQL no Microsoft Fabric e Warehouse no Microsoft Fabric. Esses programas utilizam autenticação SQL para o SQL Server. Para integração no Azure, prefira autenticação Microsoft Entra. Ambos os produtos Fabric exigem isso, e o Warehouse também exige desabilitar o Multiple Active Result Sets (MARS). Verifique o suporte do alvo selecionado para alterações de esquema, transações e procedimentos armazenados antes de reutilizar o código do SQL Server. Para diferenças de endpoint e autenticação, veja conexões Azure e Fabric.