Php ';PDO异常';带有消息';SQLSTATE[22001]:字符串数据,右截断:0
注意:我已经把这个问题缩小到专门的PDO,因为我能够使用函数成功地准备和执行语句 为什么我不能将这个参数绑定到PDO准备好的语句 这项工作:Php ';PDO异常';带有消息';SQLSTATE[22001]:字符串数据,右截断:0,php,sql-server,pdo,odbc,prepared-statement,Php,Sql Server,Pdo,Odbc,Prepared Statement,注意:我已经把这个问题缩小到专门的PDO,因为我能够使用函数成功地准备和执行语句 为什么我不能将这个参数绑定到PDO准备好的语句 这项工作: $mssqldriver = 'ODBC Driver 13 for SQL Server'; $pdoDB = new PDO("odbc:Driver=$mssqldriver;Server=$hostname;Database=$dbname", $username, $password); $pdoDB->setAttribute( PDO:
$mssqldriver = 'ODBC Driver 13 for SQL Server';
$pdoDB = new PDO("odbc:Driver=$mssqldriver;Server=$hostname;Database=$dbname", $username, $password);
$pdoDB->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$sql = "SELECT 'value' AS col where 'this' = 'this'";
$stmt = $pdoDB->prepare($sql);
$params = [];
$stmt->execute($params);
print_r($stmt->fetch());
不起作用:
$sql = "SELECT 'value' AS col where 'this' = ?";
$stmt = $pdoDB->prepare($sql);
$params = ['this'];
$stmt->execute($params);
print_r($stmt->fetch());
$sql = "SELECT * FROM myTable WHERE val = ?";
$stmt = $pdoDB->prepare($sql);
$params = ['hello world'];
$stmt->execute($params);
print_r($stmt->fetch());
Web服务器在Linux Ubuntu 14.04上运行PHP5.5.9,带有SQL Server的ODBC驱动程序13,并连接到Windows Server 2012上的Microsoft SQL Server 2012
以下是全部错误:
我还尝试设置:
$pdoDB->setAttribute( PDO::ATTR_EMULATE_PREPARES, true );
并使用命名参数:
$sql = "SELECT 'value' AS col where 'this' = :myVal";
$stmt = $pdoDB->prepare($sql);
$params = ['myVal' => 'this'];
$stmt->execute($params);
print_r($stmt->fetch());
$sql = "SELECT 'value' AS col where 'this' = :myVal";
$stmt = $pdoDB->prepare($sql);
$param = 'this';
$stmt->bindParam(':myVal', $param, PDO::PARAM_STR);
$stmt->execute();
print_r($stmt->fetch());
即使使用显式冒号:
$params = [':myVal' => 'this'];
我还尝试了使用,如中所示:
以及命名参数:
$sql = "SELECT 'value' AS col where 'this' = :myVal";
$stmt = $pdoDB->prepare($sql);
$params = ['myVal' => 'this'];
$stmt->execute($params);
print_r($stmt->fetch());
$sql = "SELECT 'value' AS col where 'this' = :myVal";
$stmt = $pdoDB->prepare($sql);
$param = 'this';
$stmt->bindParam(':myVal', $param, PDO::PARAM_STR);
$stmt->execute();
print_r($stmt->fetch());
如果我尝试显式设置长度:
$stmt->bindParam(':myVal', $param, PDO::PARAM_STR, 4);
我得到一个额外的错误:
是的,所有这些都是一个没有表格的小例子,所以你可以很容易地复制它,但为了确定,我实际上已经用一个真实的表格尝试过了
创建表myTable(
id INT标识主键,
瓦尔·纳瓦尔(255)
);
插入myTable(val)值(“hello world”);
作品:
$sql = "SELECT * FROM myTable WHERE val = 'hello world'";
$stmt = $pdoDB->prepare($sql);
$params = [];
$stmt->execute($params);
print_r($stmt->fetch());
不起作用:
$sql = "SELECT 'value' AS col where 'this' = ?";
$stmt = $pdoDB->prepare($sql);
$params = ['this'];
$stmt->execute($params);
print_r($stmt->fetch());
$sql = "SELECT * FROM myTable WHERE val = ?";
$stmt = $pdoDB->prepare($sql);
$params = ['hello world'];
$stmt->execute($params);
print_r($stmt->fetch());
所有路径都会导致相同的错误:
字符串数据,右截断
这可能不是您想要听到的,但这具有PHP的ODBC PDO驱动程序(由于PHP程序员倾向于使用MySQL/SQLite/Postgres等开源数据库而不是商业产品)或底层SQL server驱动程序(由于类似原因,Linux对其支持不足)中的所有缺陷特征,但如果odbc_*正常工作,那么它可能不是底层驱动程序 如果您尝试执行完全相同的任务,除了使用
“sqlite::memory:”
作为DSN之外,所有示例都可以工作。这使得您很可能没有做错任何事情(除非MS Server有一些我不知道的非常奇怪的不符合SQL语法)。当启用和禁用了ATTR\u EMULATE\u PREPARES
时,您的示例对我使用SQLite非常有用
我认为你能现实地做的就是希望有人捡起它。不过你可能要等很长时间
至于问题的实际解决方案,您可以选择a)切换到PHP支持的DBMS,或者b)使用SQL字符串构造,而不是预先准备好的语句,并准备好接受避免自己的负担。不过,这应该被视为最后的手段!使用可能会有所帮助,但我也会确保您的数据也经过彻底验证。我知道这不是一个理想的解决方案,但如果您必须使用MS SQL,并且迫不及待地等待PHP团队对其进行错误修复,那么我真的看不出您有多少选择
或者有一个选项c),如果odbc_*函数有效的话,可以使用它。当然,如果您想使用OOP风格,那么您必须实现自己的类,该类将过程odbc函数包装在OO方法中,因此可能需要大量的工作
编辑:我发现询问者似乎有类似的问题。他的解决方案是抛弃“官方”MS司机,转而选择FreeTDS。这可能有点像是在黑暗中拍摄,但值得一试 不幸的是,
这是一个PDO_ODBC
64位不兼容问题(,),毫无疑问,您使用的是64位构建,不允许绑定参数
幸运的是,
这首先包含在5.6版本中:
此错误也在中引用
现在还在
在5.5分支的最新稳定版本中。我看到两张票
这个问题已经存在,我正在提交这些更改
通过github提醒大家,这对任何人来说都是一个严重的问题
在x64版本上使用PDO_ODBC
PHP附带的PDO_ODBC
有什么问题?
通过查看其中一个推荐的修补程序:
diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c
index 8b0ccf3..1d275cd 100644
--- a/ext/pdo_odbc/odbc_stmt.c
+++ b/ext/pdo_odbc/odbc_stmt.c
@@ -551,7 +551,7 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
struct pdo_column_data *col = &stmt->columns[colno];
RETCODE rc;
SWORD colnamelen;
- SDWORD colsize;
+ SQLULEN colsize;
SQLLEN displaysize;
我们看到唯一改变的是SDWORD
(16位有符号整数),它被新的ODBC类型SQLULEN
取代
我相信提交人只知道colsize
数据类型,因为在下一行中SQLLEN
定义正确
我现在该怎么办?
odbc.*
函数作为工作解决方案您是否启用了ATTR\u仿真\u准备?如果你改变它会有什么不同吗?如果使用命名参数,如
选择:param as col
和bind[':param'=>'test']
,是否会有区别?我不希望有任何改变…@MichaelBerkowski我只是尝试了这两种方法,但都没有效果-相同的错误。“this”字段是什么类型?@zajonc它是字符串文字,因此其他人可以轻松复制,而无需数据集。我的实际用例涉及一个NVARCHAR(255),但我无法使它适用于任何数据类型。我想这完全是DBMS的问题,与PDO关系不大。出于好奇,您是否也可以复制所有静态查询?我的意思是,'this'='this'
?WOW64824也是我的一个bug。我垂涎你的Google Fu,因为我从未接近找到它。我担心这个补丁是为61777中引用的一个稍有不同的bug构建的,但我仍然渴望尝试。我可能需要几天时间来启动一个测试虚拟机,用这个补丁构建定制PDO,但我很兴奋,谢谢!我将该补丁与PHP7.0相关的源文件进行了比较,可以说您将做得很好@Jeffpuckettititoday我在带有php7的vm上安装了一个新的ubuntu 16.04,并确认这个问题不存在。我编辑了您的答案以包含此选项。明天我将用php5启动另一个vm,并用补丁编译以完全确认您的答案,如果成功,那么我将高兴
diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c
index 8b0ccf3..1d275cd 100644
--- a/ext/pdo_odbc/odbc_stmt.c
+++ b/ext/pdo_odbc/odbc_stmt.c
@@ -551,7 +551,7 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
struct pdo_column_data *col = &stmt->columns[colno];
RETCODE rc;
SWORD colnamelen;
- SDWORD colsize;
+ SQLULEN colsize;
SQLLEN displaysize;