Ich erhalte die Fehlermeldung "Zeichenfolgendaten, richtiges Abschneiden" von PHP mithilfe von ODBC und beim Herstellen einer Verbindung zu einer Microsoft SQL Server 2008R2-Instanz

Ich verwende PHP 5.3.3 auf einer CentOS 6.2-Box und verbinde mich mit einer Instanz von Microsoft SQL Server 2008R2. Die Verbindung funktioniert und ich kann Daten abrufen, solange meine Abfragen keine Parameter enthalten. Wenn ich Parameter hinzufüge, erhalte ich die Fehlermeldung "String-Daten, richtige Kürzung".

Hier ist ein Beispielcode:

<?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++;
}

Beachten Sie, dass beide Testfälle im obigen Code dasselbe tun sollten. Testfall 1 verwendet Parameter (wie der gesamte Code es sollte), und Testfall 2 fügt den entsprechenden Wert explizit in die SQL-Abfrage ein. Testfall 2 funktioniert. Testfall 1 nicht. Ich habe versucht, 'bindParam ()' durch 'bindValue ()' zu ersetzen, aber dies hat keine Auswirkungen. Ich habe auch versucht, benannte Parameter zu verwenden (z. B.:name) anstelle von Positionsparametern, dies hat jedoch ebenfalls keine Auswirkung. Ich habe versucht, bindParam () mit einem expliziten Längenargument zu versehen (using)strlen($param1) als Wert), aber das gibt eine wirklich bizarre Fehlermeldung (Incorrect syntax near 'OUTPUT'), und ich kann nur vermuten, dass ich es falsch mache. Ganzzahlige Parameter funktionieren ordnungsgemäß. Nur Zeichenfolgenparameter schlagen fehl.

Irgendwelche Ideen, warum das nicht funktioniert?

Natürlich ist es möglich, dass der ODBC-Treiber einen Fehler aufweist oder nicht mit meiner PHP-Version oder einer Reihe ähnlicher Probleme kompatibel ist, aber ich hoffe, dass ich die API einfach nicht ordnungsgemäß verwende.

Bearbeiten:

Per Anda Iancus Vorschlag habe ich mich mit SQL Server Profiler befasst. Bei der Verfolgung liefert Fall 1 zwei nahezu identische Datensätze, einen der KlasseSQL:BatchStartingund einer der klasseSQL:BatchCompleted, beide mit dem Text:

set fmtonly on select [name] from [myDatabase].[sys].[objects] where 1=2 set fmtonly off

Fall 2 enthält zwei Datensätze der Klasse "RPC: Completed". Der erste enthält den Text:

declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,NULL,N'select * from [myDatabase].[sys].[objects] WHERE (([name]=''testtable1''))'
select @p1

und die zweite enthält den Text:

exec sp_unprepare 1

Aktualisieren:

In einem verzweifelten Zug, in der Hoffnung, dass es ein Problem mit dem Löschen einer neuen Version von unixODBC in eine vorhandene Version von PHP geben könnte, habe ich PHP aus dem Quellcode neu kompiliert. Dies gestaltet sich unter CentOS schwieriger als Sie vielleicht denken. Dies hatte leider keine Auswirkung. Überall die gleichen Fehler.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage