4

Microsoft SQL Server 2008R2 のインスタンスに接続して、CentOS 6.2 ボックスで PHP 5.3.3 を使用しています。接続は機能し、クエリにパラメーターが含まれていない限り、データを取得できます。パラメータを追加すると、「文字列データ、右が切り捨てられました」というエラーが表示されます。

コード例を次に示します。

<?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 を不適切に使用していることを願っています。

編集:

Anda Iancu の提案に従って、私は SQL Server Profiler を掘り下げました。トレースすると、ケース 1 は 2 つのほぼ同一のレコード (1 つは class SQL:BatchStarting、もう 1 つは class ) を提供SQL:BatchCompletedし、両方にテキストが含まれています。

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

ケース 2 は、クラス "RPC:Completed" の 2 つのレコードを提供します。最初のテキストには次のテキストが含まれます。

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

2番目には次のテキストが含まれます。

exec sp_unprepare 1

アップデート:

新しいバージョンの unixODBC を既存のバージョンの PHP にドロップすることで何らかの問題が発生することを期待して、私は必死になって PHP をソースから再コンパイルしました。これは、CentOS では思ったより難しいことがわかりました。残念ながら、これは効果がありませんでした。あちこちで同じエラー。

4

2 に答える 2

7

多くの微調整と検索、および非常に多くのトラブルシューティングを行った後、最終的にこれは ODBC ドライバーの問題であると判断しました。

具体的には、RHEL/CentOS6 上の PHP および unixODBC で動作するように設計されていると思われる Microsoft からダウンロードしたドライバーを使用していました。これは、独自の README ファイルで "Microsoft ODBC Driver 11 for SQL Server" として知られており、msodbcsql-11.0.2270.0.tar.gz. (これらの詳細は、同じことをしようとしている他の人の利益のために提供されています)

私の経験に照らして、このドライバーはお勧めしません。

代わりに、FreeTDS の最新の「安定した」バージョンをダウンロード、コンパイル、およびインストールしました。あなたにとって重要な場合、私が入手したバージョンは 0.91 です (ダウンロード ファイルにはこれは記載されていませんが、この番号のディレクトリに解凍されます)。これには独自の小さな構成上の問題がありましたが、最終的には Microsoft 提供のドライバーよりもはるかにうまく機能しているようです。ディストリビューションの最新のタイムスタンプは 2011 年 8 月 17 日だったので、これがまだ積極的に維持されているかどうかはわかりません。

Microsoft ドライバーを使用して Microsoft データベース サーバーにアクセスし、実際に動作することを期待するべきだと考えている私はばかげています。

于 2013-02-01T21:07:15.093 に答える