使用PHP PDO-ODBC,unixODBC和FreeTDS的类型化绑定参数

Pie*_*yle 6 php sql-server odbc unixodbc freetds

我正在使用以下设置从PHP应用程序访问MS-SQL数据库

  • RedHat Enterprise Linux 5
  • 带有PDO和PDO_ODBC的PHP 5.2.14
  • unixODBC 2.2.11
  • FreeTDS 0.82.1.dev.20100810

非参数化查询工作正常.唯一的问题是被迫关闭单个结果语句(使用PDOStatment :: closeCursor)以避免"0 [FreeTDS] [SQL Server]无效游标状态(SQLSTATE = 24000)"错误.

但是我遇到了类型绑定参数的一个主要问题.使用这样的代码时:

$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();
}
Run Code Online (Sandbox Code Playgroud)

两列都是INT.我得到一个"206 [FreeTDS] [SQL Server]操作数类型冲突:文本与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]
Run Code Online (Sandbox Code Playgroud)

我对日志的理解是unixODBC正在尝试使用正确的类型绑定参数.但FreeTDS不支持该功能(IM001是'驱动程序不支持此功能').所以unixODBC继续没有正确打字.

有人可以确认这个诊断,或者更好的是,FreeTDS中的类型绑定参数的已知问题?如果是,他们是否使用PHP PDO工作,我可以配置它吗?

use*_*936 6

我知道这是一个老问题,但我想为遇到同样问题的人发布我的解决方案.

我能够通过将TDS版本从7.1更改为7.2来解决此问题.我没有遇到任何问题.

希望这有帮助!


Pie*_*yle 5

在FreeTDS邮件列表中,我得到了FreeTDS不支持SQLDescribeParam确认.但是当不支持SQLDescribeParam时,PDO_ODBC应该归咎于使用LONGVARCHAR(即文本).

相同的代码在带有PDO ODBC的Windows工作站上运行(PHP版本5.2.9,ODBC库Win32)

此问题的解决方法是将每个参数视为LONGVARCHAR并在查询中使用显式类型转换.MS SQL Server仅支持LONGVARCHAR =>*CHAR转换.要转换,我不得不使用像CAST(CAST(:number AS varchar) AS INTEGER)或的东西CAST(CAST(:birthdate AS varchar) AS datetime).这是糟糕的,丑陋的,可能是一场表演,但它确实有效.