Estou recebendo erros de "String de dados, truncagem correta" do PHP usando ODBC e conectando a uma instância do Microsoft SQL Server 2008R2
Estou usando o PHP 5.3.3 em uma caixa do CentOS 6.2, conectando-me a uma instância do Microsoft SQL Server 2008R2. A conexão funciona e posso recuperar dados, desde que minhas consultas não contenham parâmetros. Quando eu adiciono parâmetros, recebo o erro "String data, right truncation".
Aqui está um código de exemplo:
<?php
$dbh = new PDO("odbc:myDSN", 'myUsername', 'myPassword');
$testCase = 1;
switch ($testCase) {
case 1:
// This case fails with this error:
// Error 22001: [Microsoft][ODBC Driver 11 for SQL Server]String data, right truncation (SQLExecute[0] at /builddir/build/BUILD/php-5.3.3/ext/pdo_odbc/odbc_stmt.c:254)
$query = "select * from [myDatabase].[sys].[objects] WHERE (([name]=?))";
$stmt = $dbh->prepare($query);
$param1 = 'testtable1';
$stmt->bindParam(1, $param1, PDO::PARAM_STR); // Note: '1' is correct; it should not be '0'
break;
case 2:
// This case works properly
$query = "select * from [myDatabase].[sys].[objects] WHERE (([name]='testtable1'))";
$stmt = $dbh->prepare($query);
break;
}
$execResult = $stmt->execute();
if ($execResult) {
print "Success!\n";
} else {
$errorInfo = $stmt->errorInfo();
print "Error " . $stmt->errorCode() . ": " . $errorInfo[2] . "\n";
}
$rowCount = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "Row " . $rowCount . ":\n";
foreach ($row as $key => $value) {
printf(" %-20s %s\n", $key, $value);
}
$rowCount++;
}
Observe que ambos os casos de teste no código acima devem fazer a mesma coisa. O caso de teste 1 usa parâmetros (como todo o código deve) e o caso de teste 2 coloca explicitamente o valor relevante na consulta SQL. O caso de teste 2 funciona. Caso de teste 1 não. Eu tentei substituir 'bindParam ()' com 'bindValue ()', mas isso não tem efeito. Eu também tentei usar parâmetros nomeados (por exemplo,:name
) em vez de parâmetros posicionais, mas isso também não tem efeito. Eu tentei adicionar um argumento de comprimento explícito para bindParam () (usandostrlen($param1)
como um valor), mas isso dá uma mensagem de erro muito bizarra (Incorrect syntax near 'OUTPUT'
), e só posso supor que estou fazendo errado. Parâmetros inteiros funcionam corretamente. Apenas parâmetros de string falham.
Alguma idéia de por que isso não está funcionando?
É claro que é possível que haja um bug no driver ODBC, ou que não seja compatível com a minha versão do PHP, ou qualquer outro problema semelhante, mas espero que esteja usando a API de maneira inadequada.
Editar:
Sugestão de Per Anda Iancu, investiguei o SQL Server Profiler. Quando rastreado, o caso 1 fornece dois registros quase idênticos, um de classeSQL:BatchStarting
, e um de classeSQL:BatchCompleted
ambos contendo o texto:
set fmtonly on select [name] from [myDatabase].[sys].[objects] where 1=2 set fmtonly off
O caso 2 fornece dois registros, ambos da classe "RPC: Concluído". O primeiro contém o texto:
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,NULL,N'select * from [myDatabase].[sys].[objects] WHERE (([name]=''testtable1''))'
select @p1
e o segundo contém o texto:
exec sp_unprepare 1
Atualizar:
Em um movimento desesperado, esperando que pudesse haver algum tipo de problema ao lançar uma nova versão do unixODBC em uma versão existente do PHP, eu recompilei o PHP do código-fonte. Isso acaba sendo mais difícil do que você imagina, no CentOS. Infelizmente, isso não teve efeito. Mesmos erros ao redor.