Я получаю ошибки «String data, right truncation» из PHP с использованием ODBC и подключение к экземпляру Microsoft SQL Server 2008R2

Я использую PHP 5.3.3 в поле CentOS 6.2, подключаясь к экземпляру Microsoft SQL Server 2008R2. Соединение работает, и я могу получить данные, пока мои запросы не содержат параметров. Когда я добавляю параметры, я получаю сообщение об ошибке «Строковые данные, правильное усечение».

Вот пример кода:

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

Обратите внимание, что оба тестовых примера в коде выше должны делать то же самое. В тестовом примере 1 используются параметры (как и весь код), а тестовый пример 2 явно помещает соответствующее значение в запрос SQL. Тестовый корпус 2 работает. В тестовом случае 1 нет. Я попытался заменить 'bindParam ()' на 'bindValue ()', но это не имеет никакого эффекта. Я также попытался использовать именованные параметры (например,: :name ) вместо позиционных параметров, но это также не имеет никакого эффекта. Я попытался добавить аргумент явной длины в bindParam () (используя значение strlen($param1) в качестве значения), но это дает действительно странное сообщение об ошибке ( Incorrect syntax near 'OUTPUT' ), и я могу только предположить, я делаю это неправильно. Целочисленные параметры работают правильно. Только строковые параметры терпят неудачу.

Любые идеи, почему это не работает?

Конечно, возможно, что в драйвере ODBC есть ошибка, или что она несовместима с моей версией PHP или с любым количеством подобных проблем, но я надеюсь, что я просто неправильно использую API.

Редактировать:

По предложению Анды Ианку я углубился в SQL Server Profiler. При прослеживании случай 1 дает две почти идентичные записи: один из классов SQL:BatchStarting и один из классов SQL:BatchCompleted , оба содержат текст:

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

Случай 2 дает две записи, оба класса «RPC: Completed». Первый содержит текст:

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

а второй содержит текст:

 exec sp_unprepare 1 

Обновить:

В отчаянном движении, надеясь, что может возникнуть какая-то проблема с отбрасыванием новой версии unixODBC в существующую версию PHP, я перекомпилировал PHP из исходного кода. Это оказывается сложнее, чем вы могли бы подумать, на CentOS. К сожалению, это не повлияло. Одинаковые ошибки.

После тщательной настройки и поиска, а также для устранения неполадок, я наконец решил, что это проблема драйвера ODBC.

В частности, я использовал драйвер, загруженный из Microsoft, предположительно разработанный для работы с PHP и unixODBC на RHEL / CentOS6. Он известен как «Microsoft ODBC Driver 11 для SQL Server» в собственном файле README и поставляется в файле msodbcsql-11.0.2270.0.tar.gz . (Эти данные предоставлены в интересах любого другого, кто пытается сделать то же самое)

В свете моего опыта я не рекомендую этот драйвер.

Я скачал, скомпилировал и установил последнюю «стабильную» версию FreeTDS. Если это имеет значение для вас, версия, которую я получил, – 0.91 (файл загрузки не говорит об этом, но он распаковывается в каталог с этим номером). Это имело / имело свои незначительные проблемы с конфигурацией, но в конечном итоге, похоже, работает намного лучше, чем драйвер, предоставленный Microsoft. Я не знаю, поддерживается ли это по-прежнему, поскольку самые последние временные метки в распространении были 17 августа 2011 года.

Глупый я, полагая, что я должен использовать драйвер Microsoft для доступа к серверу базы данных Microsoft и ожидать, что он действительно сделает то, что он говорит, что это будет делать.

Я думаю, что вы, вероятно, столкнулись с ошибкой в ​​ODBC-драйвере Microsoft, но стоит отметить, что pdo_odbc имеет критическую ошибку, связанную с функцией bindValue () . Ошибка затрагивает только 64-битные но-га! – Драйвер ODBC от Microsoft только 64-разрядный.

Это было какое-то время, но я думаю, что ошибка, которую вы нажимаете, зависит от ваших типов данных и оператора SQL.