Otrzymuję błędy „String data, right truncation” z PHP za pomocą ODBC i łączenie się z instancją Microsoft SQL Server 2008R2
Używam PHP 5.3.3 na pudełku CentOS 6.2, łącząc się z instancją Microsoft SQL Server 2008R2. Połączenie działa i mogę pobrać dane, o ile moje zapytania nie zawierają żadnych parametrów. Gdy dodaję parametry, pojawia się błąd „Dane ciągu, prawe obcięcie”.
Oto przykładowy kod:
<?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++;
}
Zauważ, że oba przypadki testowe w powyższym kodzie powinny zrobić to samo. Przypadek testowy 1 wykorzystuje parametry (jak powinien być cały kod), a przypadek testowy 2 wyraźnie umieszcza odpowiednią wartość w zapytaniu SQL. Działa test case 2. Przypadek testowy 1 nie. Próbowałem zastąpić 'bindParam ()' za pomocą 'bindValue ()', ale nie ma to żadnego skutku. Próbowałem również użyć nazwanych parametrów (np.:name
) zamiast parametrów pozycyjnych, ale to również nie ma wpływu. Próbowałem dodać jawny argument długości do bindParam () (używającstrlen($param1)
jako wartość), ale daje to naprawdę dziwny komunikat o błędzie (Incorrect syntax near 'OUTPUT'
) i mogę tylko założyć, że robię to źle. Parametry całkowite działają poprawnie. Tylko parametry ciągu zawodzą.
Jakieś pomysły, dlaczego to nie działa?
Oczywiście jest możliwe, że w sterowniku ODBC występuje błąd lub że nie jest on zgodny z moją wersją PHP lub z wieloma podobnymi problemami, ale mam nadzieję, że po prostu używam API nieprawidłowo.
Edytować:
Według sugestii Andy Iancu zagłębiłem się w SQL Server Profiler. W przypadku śledzenia przypadek 1 daje dwie prawie identyczne rekordy, jedną klasySQL:BatchStarting
i jeden z klasySQL:BatchCompleted
, oba zawierające tekst:
set fmtonly on select [name] from [myDatabase].[sys].[objects] where 1=2 set fmtonly off
Przypadek 2 daje dwa rekordy, obie klasy „RPC: Completed”. Pierwszy zawiera tekst:
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,NULL,N'select * from [myDatabase].[sys].[objects] WHERE (([name]=''testtable1''))'
select @p1
a drugi zawiera tekst:
exec sp_unprepare 1
Aktualizacja:
W desperackim ruchu, mając nadzieję, że pojawi się jakiś problem z upuszczeniem nowej wersji unixODBC do istniejącej wersji PHP, przekompilowałem PHP ze źródła. To okazuje się trudniejsze niż mogłoby się wydawać w CentOS. Niestety nie miało to żadnego skutku. Te same błędy dookoła.