PYODBC截断SQL Server FOR JSON查询结果的问题排查
解决PyODBC调用SQL Server存储过程返回JSON结果截断的问题
我之前也踩过这个坑!当用PyODBC调用返回JSON的SQL Server存储过程时,结果截断是个很常见的问题——毕竟SSMS里跑着正常,到Python里就出问题,确实让人头大。下面是我亲测有效的解决思路和办法:
1. 调整PyODBC的字符串长度限制
PyODBC默认对字符串类型的返回值有长度限制,这是导致JSON被截断的最常见原因。你可以通过两种方式解决:
- 连接时设置全局参数:在创建数据库连接时,指定
MAX_VARCHAR_SIZE=0(0表示不限制长度):import pyodbc conn_str = ( "DRIVER={ODBC Driver 17 for SQL Server};" "SERVER=你的服务器地址;" "DATABASE=你的数据库;" "UID=用户名;" "PWD=密码" ) conn = pyodbc.connect(conn_str, MAX_VARCHAR_SIZE=0) - 针对游标设置输出大小:在执行存储过程前,给游标设置对应类型的输出大小:
cursor = conn.cursor() # SQL_WVARCHAR对应NVARCHAR类型,0表示不限制长度 cursor.setoutputsize(0, pyodbc.SQL_WVARCHAR) cursor.execute("EXEC 你的存储过程名")
2. 优化存储过程的JSON返回逻辑
有时候SQL Server本身返回FOR JSON结果时,可能会因为默认的返回方式导致分段。你可以修改存储过程,把JSON结果先存入NVARCHAR(MAX)变量再输出,确保返回的是完整的单个字符串:
CREATE PROCEDURE 你的存储过程名 AS BEGIN SET NOCOUNT ON; -- 先把JSON结果存入变量 DECLARE @fullJson NVARCHAR(MAX); SET @fullJson = (SELECT * FROM 你的表 FOR JSON PATH); -- 输出完整的JSON字符串 SELECT @fullJson AS JsonResult; END
3. 正确读取Python中的结果
如果前面两步都做了,还是有截断的情况,可以尝试拼接所有返回行(极端情况下SQL Server可能会把长JSON拆分成多行返回):
cursor.execute("EXEC 你的存储过程名") # 拼接所有行的内容 full_json = ''.join([row[0] for row in cursor.fetchall()])
为什么会出现这个问题?
简单来说,PyODBC默认不会自动处理NVARCHAR(MAX)这类大长度字符串,而SELECT...FOR JSON PATH返回的内容很容易超过它的默认长度限制。SSMS会自动处理大字符串的拼接,所以看起来正常,但PyODBC需要我们手动配置来支持完整读取。
内容的提问来源于stack exchange,提问作者Mark Sinkinson




