我们注意到这样的错误:
InterfaceError: ('HY104', 0, '[Microsoft][SQL Server Native Client 11.0]
Invalid precision value', 10226)
当我们插入一定长度的字符以及 Unicode 内容(如\u3000
(表意空间))时,就会发生这种情况。仅当我们使用 Windows MSSQL 驱动程序并且查询已参数化时才会发生这种情况。
该列是一个VARCHAR(MAX)
. 所以它应该支持2GB。
- 这可能是什么原因?
- 为什么长度很重要?
如果我只插入这个 Unicode 字符,它不会引起问题!
我试图从理论的角度来看待这一点。切换到NVARCHAR
目前不是我们的选择,但删除 Unicode 是。
根据 Solomon Rutzky 提出的问题,以下是更多详细信息:
- 列排序规则是
SQL_Latin1_General_CP1_CI_AS
- 我开始看到错误的字符串长度是
4019
. sqlalchemy.connectors.mxodbc, line 86, in error_handler
是我得到初始错误的地方。这是来自追溯。- 它适用于单个 Unicode 字符。
- 没有 Unicode 的 20000 个字符串可以正常工作。
- 当我从这个软件(Web App)尝试这个时,它就变成了ASCII。我通过导出数据在 Dbeaver 中进行了测试。
了解以下内容将大有帮助:
VARBINARY(MAX)
。Unicode 字符是否被翻译或其他?有可能出错的字符串刚好超过 4000 或 8000 个字符的限制,然后需要使用
MAX
类型,并且驱动程序最初猜测(或被告知)它是一种大小,然后发现它是另一种大小。错误消息说“无效的精度值”必须指的是列的配置方式(即类似于SqlParameter
在 .NET 中设置 a 并声明最大大小,例如new SqlParameter("@name", SqlDbType.VarChar, 8000)
)。因此,只有当软件尝试将列设置为VARCHAR
超过 8000 或NVARCHAR
超过 4000 时,才会真正发生这种类型的错误,因为这些条件中的任何一个都是无效的“精度”。现在,为了得到这样一个数字,我怀疑那里的一些代码正在计算字节数(即DATALENGTH
) 的字符串,这将大于字符数。当然,对于 .NETstring
或 C++中的任何字符都是如此wchar
,所以我怀疑有一些 Unicode 字符与没有任何字符的区别在于,没有任何 Unicode 字符,它可以将字符串转换为 8 位编码(即与 一起使用的单字节VARCHAR
),但不知何故,有一个 Unicode 字符会阻止这种情况。这是一个长镜头(直到提供更多信息),但很清楚错误发生在哪里。你是如何插入角色的?通过产生错误的同一软件,还是在 SSMS 中?如果您通过
INSERT
语句手动执行此操作,那么这不是一个好的测试,因为 SQL Server 将 U+3000 转换为常规空格 U+0020(一个字节),而不是两个问号(仍然是 2 个字节,就像如果没有等效字符,则会发生):返回:
如果可能,尝试通过软件而不是通过 SSMS 传入由以下代码生成的两个字符串:
该
@String4k
字符串是 3999 个字符,可以完全转换为 8 位编码(即VARCHAR
)加上可能保留为 2 个字节的 U+3000 字符。因此,通过该软件,这可能会显示为 4001 个字符。我怀疑这是问题所在,但测试也无妨。该
@String8k
字符串是 7999 个字符,可以干净地转换为 8 位编码(即VARCHAR
)加上可能保留为 2 个字节的 U+3000 字符。因此,通过该软件,这可能会以 8001 个字符的形式出现。