我正在使用 pyodbc 对 Azure SQL 数据仓库运行 UPDATE 语句:
cursor.execute(
"UPDATE dbo.test SET desc = ? WHERE id = ?", desc, id
)
当 desc 值很简单时,这很有效。但是当 desc 的值更复杂(更长的文本)时,执行上面的命令会出现以下错误:
pyodbc.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]104220;
Cannot find data type 'ntext'. (100000) (SQLExecDirectW)")
我以为逃避可以解决任何问题,但事实并非如此。有什么想法/见解吗?
你能试试这个吗:
cursor.execute(
"UPDATE dbo.test SET desc = CAST(? AS NVARCHAR(MAX)) WHERE id = ?", desc, id
)
我猜 pyodbc 正在以某种方式将大字符串转换为
ntext
。
如果这没有帮助,请检查以下github链接 - 它可能会对您有所帮助,因为它解释了如果:
您正在使用旧的 SQL Server (WDAC) 驱动程序,该驱动程序将 nvarchar 视为 ntext,这就是您遇到此问题的原因,因为没有 引用 django-pyodbc-azure 中的 ntext 类型
更新 - 2022-02-21:
SQL Server 的 ODBC 驱动程序 18 添加了一个LongAsMax
连接字符串参数,因此我们可以告诉驱动程序将长类型映射为更现代的
*(max)
类型,而不是旧的
TEXT/NTEXT/IMAGE
类型。更多信息这里。
GitHub 问题中的建议,解决方法是使用 setinputsizes 作为 ODBC 驱动程序的提示:
# test data
desc = ' '.join(['abcde' for x in range(2000)])
crsr.setinputsizes([(pyodbc.SQL_WVARCHAR, 0), (pyodbc.SQL_INTEGER,)])
crsr.execute("UPDATE ##test SET [desc]=? WHERE id=?", desc, id)
有驱动发送的效果
exec sp_prepare @p1 output,N'@P1 nvarchar(max),@P2 int',N'UPDATE ##test SET [desc]=@P1 WHERE id=@P2',1
而不是
exec sp_prepare @p1 output,N'@P1 ntext,@P2 int',N'UPDATE ##test SET [desc]=@P1 WHERE id=@P2',1
connectionString = f'DRIVER={{ODBC Driver 18 for SQL Server}};SERVER={HOST};DATABASE={DB};UID={UID};PWD={PWD};Authentication=ActiveDirectoryPassword;**LongAsMax=yes**;'