6

次の設定を使用して、PHPアプリケーションからMS-SQLデータベースにアクセスしています

  • RedHat Enterprise Linux 5
  • PDOおよびPDO_ODBCを使用したPHP5.2.14
  • unixODBC 2.2.11
  • FreeTDS 0.82.1.dev.20100810

パラメータ化されていないクエリは正常に機能します。唯一の問題は、「0 [FreeTDS] [SQL Server]無効なカーソル状態(SQLSTATE = 24000)」エラーを回避するために、単一の結果ステートメント(PDOStatment :: closeCursorを使用)でカーソルを閉じることを強制されることです。

しかし、型指定されたバインドされたパラメーターに大きな問題があります。このようなコードを使用する場合:

$stmt = $PDO->prepare('INSERT INTO table (column1, column2)  VALUES (:foo, :bar');
$stmt->bindValue(':foo', 21, PDO::PARAM_INT);
$stmt->bindValue(':bar', 42, PDO::PARAM_INT);
$stmt->execute():
if (!$stmt->execute()) {
 var_dump($stmt->errorInfo();
}

ここで、両方の列はINTです。「206[FreeTDS][SQL Server] Operand type clash:text is incompatible with int [SQLSTATE=22018]」エラーが発生します。

unixODBCログでは、次のようなものが得られます

[ODBC][26251][SQLDescribeParam.c][175]
              Entry:
                      Statement = 0x2b73c849fb80
                      Parameter Number = 1
                      SQL Type = 0x7fff9c89e15e
                      Param Def = 0x7fff9c89e154
                      Scale = 0x7fff9c89e15c
                      Nullable = 0x7fff9c89e15a
[ODBC][26251][SQLDescribeParam.c][276]Error: IM001
[ODBC][26251][SQLBindParameter.c][193]
              Entry:
                      Statement = 0x2b73c849fb80
                      Param Number = 1
                      Param Type = 1
                      C Type = 1 SQL_C_CHAR
                      SQL Type = -1 SQL_LONGVARCHAR
                      Col Def = 4000
                      Scale = 5
                      Rgb Value = 0x2b73c941f890
                      Value Max = 0
                      StrLen Or Ind = 0x2b73c93fa1b0
[ODBC][26251][SQLBindParameter.c][339]
              Exit:[SQL_SUCCESS]

ログについての私の理解は、unixODBCが正しいタイプを使用してパラメーターをバインドしようとしているということです。ただし、FreeTDSはこの機能をサポートしていません(IM001は「ドライバはこの機能をサポートしていません」です)。したがって、unixODBCは適切な入力なしで続行します。

誰かがこの診断を確認できますか、より良いのは、FreeTDSの型付きバインドパラメータに関する既知の問題ですか?はいの場合、PHP PDOを使用して動作しますか?構成できますか?

4

3 に答える 3

6

これは古い問題であることは知っていますが、同じ問題を抱えている人のために解決策を投稿したいと思いました。

TDSバージョンを7.1から7.2に変更することで、この問題を解決することができました。もう問題は発生していません。

うまくいけば、これが役立ちます!

于 2012-03-07T21:40:53.377 に答える
5

FreeTDSメーリングリストで、SQLDescribeParamがFreeTDSでサポートされていないことを確認しました。ただし、SQLDescribeParamがサポートされていない場合、PDO_ODBCはLONG​​VARCHAR(つまりテキスト)の使用を非難します。

同じコードが、PDO ODBC(PHPバージョン5.2.9、ODBCライブラリWin32)を備えたWindowsワークステーションで機能しました。

この問題の回避策は、すべてのパラメーターをLONGVARCHARとして扱い、クエリで明示的な型変換を使用することです。MS SQL Serverは、LONGVARCHAR =>*CHAR変換のみをサポートします。変換するには、CAST(CAST(:number AS varchar) AS INTEGER)またはのようなものを使用する必要がありCAST(CAST(:birthdate AS varchar) AS datetime)ました。それは悪い、醜い、そしておそらくパフォーマンスの独り占めですが、それは機能します。

于 2010-10-04T08:56:56.317 に答える
0

私の場合、レコードを返すストアドプロシージャを呼び出しましたが、いくつかの挿入が含まれています...次を追加することで機能させることができました。

SET NOCOUNT ON

挿入の場合、MSSQLは挿入の結果を出力しますが、PDOはそれを理解しないため、これは同様である可能性があります。

あなたが言ったようにキャストをすることは私にとってうまくいきませんでした。

動作を再現する方法の例:

create procedure sptest 
    @var int
as
begin 
    create table #tmp (var int)
    insert into #tmp values (@var)
    select * from #tmp
end

そしてPHPコード:

$query = "exec sptest @var=:var";
$dbh = new PDO (SQLSVR_DRIVER);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$rs = $dbh->prepare($query);
$rs->bindParam('var', 1, PDO::PARAM_INT);
$rs->execute();
while ($row = $rs->fetch(PDO::FETCH_ASSOC))
    var_dump($row);

修正は次のとおりです。

create procedure sptest 
    @var int
as
begin 
    set nocount on
    create table #tmp (var int)
    insert into #tmp values (@var)
    select * from #tmp
end

それでおしまい!

于 2013-09-23T06:46:16.930 に答える