问题描述
我正在使用以下设置从PHP应用程序访问MS-SQL数据库
I'm using the following setup to access a MS-SQL database from a PHP application
- 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)"错误.
Unparametrized queries work fine. The only issue is being forced to close cursor on single result statements (with PDOStatment::closeCursor) to avoid "0 [FreeTDS][SQL Server] Invalid cursor state (SQLSTATE=24000)" errors.
但是我在键入绑定参数方面遇到了一个主要问题.当使用这样的代码时:
But I'm having a major issue with typed bound parameter. When using code like this:
$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类型冲突:文本与int [SQLSTATE = 22018]不兼容"错误.
Where both columns are INT. I get the an "206 [FreeTDS][SQL Server]Operand type clash: text is incompatible with int [SQLSTATE=22018]" error.
在unixODBC日志中,我得到类似
In the unixODBC log, I get something like
[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会在没有正确键入的情况下继续.
My understanding of the log is that unixODBC is trying to bind the parameters using the right type. But the FreeTDS doesn't support the function (IM001 is 'Driver does not support this function'). So unixODBC continue without proper typing.
有人可以确认这种诊断,或者更好的是,在FreeTDS中键入绑定参数存在一个已知问题吗?如果是,它们是否可以使用PHP PDO工作,我可以对其进行配置吗?
Can someone confirm this diagnosis or, better, a known issue with typed bound parameter in FreeTDS ? If yes, do they work using PHP PDO and hwo can I configure it ?
推荐答案
在FreeTDS邮件列表上,我得到了确认FreeTDS不支持SQLDescribeParam .但是,当不支持SQLDescribeParam时, PDO_ODBC是使用LONGVARCHAR(即文本)的罪魁祸首.
On the FreeTDS mailing list, I got the confirmation that SQLDescribeParam is not supported in FreeTDS. But when SQLDescribeParam is not supported, PDO_ODBC is to blame for using LONGVARCHAR (ie. text).
相同的代码在带有PDO ODBC(PHP版本5.2.9,ODBC库Win32)的Windows工作站上工作
The same code worked on a Windows workstation with PDO ODBC (PHP Version 5.2.9, ODBC library Win32)
此问题的解决方法是将每个参数都视为LONGVARCHAR并在查询中使用显式类型转换. MS SQL Server仅支持LONGVARCHAR => * CHAR转换一个>.要进行转换,我必须使用CAST(CAST(:number AS varchar) AS INTEGER)
或CAST(CAST(:birthdate AS varchar) AS datetime)
之类的东西.这很糟糕,很丑陋,而且可能会降低性能,但是它可以工作.
A workaround for this issue to treat every parameter as LONGVARCHAR and use explicit type conversion in queries. MS SQL Server only supports LONGVARCHAR => *CHAR conversions. To convert, I had to use thing like CAST(CAST(:number AS varchar) AS INTEGER)
or CAST(CAST(:birthdate AS varchar) AS datetime)
. It is bad, ugly and probably a performance hog but it works.
这篇关于将类型化的绑定参数与PHP PDO-ODBC,unixODBC和FreeTDS一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!