当TVP数据第一行为None时出现“无效SQL数据类型”错误

0 投票
1 回答
62 浏览
提问于 2025-04-14 17:26

我在用pyodbc启动SQL Server数据库中的存储过程时遇到了一个错误,这个存储过程使用了表值参数(TVP),而且有一列的值是None。

[HY004] [Microsoft][ODBC Driver 18 for SQL Server]无效的SQL数据类型 (0) (SQLBindParameter)

有没有办法告诉pyodbc这列的具体数据类型,还是说我必须放弃使用表值参数(TVP)?

这是我正在尝试的:

cursor.execute("{CALL dbo.stored_procedure (?, ?)}", (None, tvp_data))

第一个变量我不在乎,第二个是我的表值参数(TVP)。只要在TVP的某一列中没有None,所有操作都正常,但如果有None,我就会遇到这个错误。

1 个回答

1

这是一个已知的问题,关于参数元数据发现的限制,具体讨论可以在GitHub上找到,链接在这里这里。解决这个问题的方法有:

选项1:对你的TVP数据进行排序,确保第一行没有None值。

选项2:在一个匿名代码块中使用OPENJSON(),并将你的TVP数据作为JSON字符串传递。

tvp_data = [(1, None), (2, "Bravo")]
tvp_json = [dict(zip(["id", "txt"], row)) for row in tvp_data]

sql = """\
SET NOCOUNT ON;
DECLARE @tvp dbo.issue_1229_table_type;
INSERT INTO @tvp (id, txt)
SELECT id, txt FROM OPENJSON(?)
WITH (
    id int '$.id',
    txt nvarchar(50) '$.txt'
);
EXEC issue_1229_sp @tvp
"""
results = crsr.execute(sql, json.dumps(tvp_json, default=str)).fetchall()
print(results)
# [(1, None), (2, 'Bravo')]

(这个例子是我自己在GitHub评论中复制的,链接在这里。)

撰写回答