问题
使用带有PDO和ODBC驱动程序的预准备语句执行插入时,如果至少有一个参数超过30个字符,则会出现以下错误:
SQLSTATE[HY010]: Function sequence error: 0
[unixODBC][Driver Manager]Function sequence error (SQLExecute[0] at /usr/src/builddir/ext/pdo_odbc/odbc_stmt.c:254)
插入适用于任何长度<= 30个字符的绑定字符串。
我对SELECT
查询没有任何问题。
将INSERT
与isql
和sqlcmd
一起使用不会产生错误,但如果超过30个字符,则会在数据库中截断列值。
这似乎是一个驱动程序问题。
关于导致问题的原因以及如何解决问题的任何想法?
示例
以下是使用PHP isql
和sqlcmd
复制系统错误的最小示例。
使用的表(称为table
)有三列:
colvarchar varchar(70)
colnvarchar nvarchar(40)
colnchar nchar(60)
产生错误的代码:
<?php
$dns = 'odbc:testdb';
$username = 'user';
$password = 'pass';
$pdo = new PDO($dns, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = <<<'QUERY'
INSERT INTO table
(colvarchar, colnvarchar, colnchar)
VALUES
(CAST(:colvarchar AS varchar)
CAST(:colnvarchar AS nvarchar),
CAST(:colnchar AS nchar));
QUERY;
$prepStmt = $pdo->prepare($sql);
// Add one more characters to any of the following strings to cause the error
$prepStmt->bindValue('colvarchar', '012345678901234567890123456789');
$prepStmt->bindValue('colnvarchar', '012345678901234567890123456789');
$prepStmt->bindValue('colnchar', '012345678901234567890123456789');
$prepStmt->execute();
?>
向30个字符串中的任何一个添加其他字符将导致以下错误:
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY010]: Function sequence error: 0 [unixODBC][Driver Manager]Function sequence error (SQLExecute[0] at /usr/src/builddir/ext/pdo_odbc/odbc_stmt.c:254)' in ...
从命令行使用isql
和sqlcmd
执行插入,但表中的select显示字符串被截断为30个字符。
slqcmd:
sqlcmd -D -S testdb -U user -P pass -q“INSERT INTO table(colvarchar, colnvarchar,colnchar)价值观 (CAST('012345678901234567890123456789xxx'AS varchar), CAST('012345678901234567890123456789xxx'AS nvarchar), CAST('012345678901234567890123456789xxx'AS nchar))“
(受影响的一行)
ISQL:
isql testdb -U user -P pass
SQL&GT; INSERT INTO表(colvarchar, colnvarchar,colnchar)价值观 (CAST('012345678901234567890123456789xxx'AS varchar), CAST('012345678901234567890123456789xxx'AS nvarchar), CAST('012345678901234567890123456789xxx'AS nchar))“
SQLRowCount返回1
结果:
SELECT colvarchar, colnvarchar, colnchar FROM table;
colvarchar | colnvarchar | colnchar
012345678901234567890123456789 | 012345678901234567890123456789 | 012345678901234567890123456789
012345678901234567890123456789 | 012345678901234567890123456789 | 012345678901234567890123456789
研究
此post详细说明了与不符合最大列宽,时间戳格式或列类型的插入类似的问题。
varchar
。系统设置
更新
我相信这是一个unixODBC问题,因为当我使用FreeTDS和unixODBC(因为这个问题而改为MS ODBC和unixODBC)时出现了30个字符的截断。不同之处在于使用FreeTDS时没有错误消息;它像isql
和sqlcmd
目前一样无声地失败。
将unixODBC版本从2.3.4更改为2.3.0,因为它与MS ODBC 11兼容,如here所示。问题仍然存在。
所有需要ODBC共享库的程序都链接到2011年的版本。它们现在都与unixODBC的日期更新共享库相关联。问题仍然存在。
答案 0 :(得分:1)
您在SQL-Server
中CAST到NVARCHAR和NVARCHAR限制为30个字符像这样制作演员: CAST(colvarchar AS varchar(70)) CAST(colnvarchar AS nvarchar(40)) CAST(colnchar AS nchar(60))
答案 1 :(得分:0)
问题在于SQL CAST
表达式。
截断和舍入结果
转换字符或二进制表达式时(char,nchar, nvarchar,varchar,binary或varbinary)到a的表达式 不同的数据类型,数据可以被截断,只能部分显示, 或者返回错误,因为结果太短而无法显示。
文档列出了保证不会被截断的特定异常。但是,它没有详细说明将截断的长度数据。
指定数据类型长度以避免截断:
CAST (colvarchar AS varchar(70))
CAST (colnvarchar AS nvarchar(40))
CAST (colnchar AS nchar(60))