You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python从SQL Server获取XML数据时内容被截断问题

SQL Server查询XML数据时pyodbc截断前2037字符的问题

问题描述

使用pyodbc从SQL Server查询XML格式数据并写入唯一命名的XML文件,小数据量时正常,但数据长度超过2037字符时,仅返回前2037字符。尝试pymssql、fetchval()、fetchone()、fetchall()均存在截断问题。

环境信息

  • SQL Server版本:15.0.2000.5(SQL Server 2019 Express)
  • 驱动:ODBC Driver 17 for SQL Server
  • Python版本:3.11.1
  • pyodbc版本:4.0.35
  • 运行环境:Windows Server 2016 Standard

用于查询XML的SQL语句

SELECT 
  C.BLKODU AS "BLKODU", 
  C.CARIKODU AS "CARIKODU", 
  C.TICARI_UNVANI AS "TICARI_UNVANI", 
  C.ADI_SOYADI AS "ADI_SOYADI", 
  C.VERGI_NO AS "VERGI_NO", 
  C.TC_KIMLIK_NO AS "TC_KIMLIK_NO", 
  C.VERGI_DAIRESI AS "VERGI_DAIRESI", 
  C.CEP_TEL AS "CEP_TEL", 
  C.ILI AS "ILI", 
  C.ILCESI AS "ILCESI", 
  C.ADRESI_1 AS "ADRESI", 
  (SELECT 
      CHR.BLKODU AS "BLKODU", 
      CHR.EVRAK_NO AS "EVRAK_NO", 
      CHR.MAKBUZNO AS "MAKBUZ_NO", 
      CAST(CHR.TARIHI AS DATE) AS "TARIHI", 
      CAST(CHR.VADESI AS DATE) AS "VADESI",  
      CHR.MUH_DURUM AS "MUH_DURUM", 
      CAST(CHR.KPB_ATUT AS DECIMAL(10, 2)) AS "KPB_ATUT", 
      CAST(CHR.KPB_BTUT AS DECIMAL(10, 2)) AS "KPB_BTUT" 
   FROM CARIHR AS CHR 
   WHERE CHR.BLCRKODU = C.BLKODU 
   ORDER BY CHR.TARIHI
   FOR XML PATH('CARIHR'), TYPE) 
FROM CARI AS C 
WHERE C.CARIKODU = 'CR00001'
FOR XML PATH ('CARI')

最初的Python代码

import pyodbc
import uuid
import codecs

import query
import core

conn = pyodbc.connect(core.connection_string, commit=True)
cursor = conn.cursor()
cursor.execute(query.ctr)
row = cursor.fetchval()
id = uuid.uuid4()
xml_file = "./temp/"+str(id)+".xml"
xml = codecs.open(xml_file, "w", "utf-8")
xml.write(row)
xml.close()

尝试过的其他方法

import pyodbc
import uuid
import codecs

conn = pyodbc.connect(connect_string, commit=True)
cursor = conn.cursor()
cursor.execute(query.ctr)
row = cursor.fetchall()
data = ','.join(row[0])
id = uuid.uuid4()
xml_file = "./temp/"+str(id)+".xml"
xml = codecs.open(xml_file, "w", "utf-8")
xml.write(data)
xml.close()

解决方案

方法一:读取完整的大对象内容

SQL Server返回的XML类型在pyodbc中被视为Large Object(LOB),默认仅返回前2037字符。需要调用read()方法获取完整内容:

import pyodbc
import uuid
import codecs

import query
import core

conn = pyodbc.connect(core.connection_string, commit=True)
cursor = conn.cursor()
cursor.execute(query.ctr)
row = cursor.fetchone()
# 对XML类型字段调用read()获取全部内容
xml_content = row[0].read()
id = uuid.uuid4()
xml_file = "./temp/"+str(id)+".xml"
with codecs.open(xml_file, "w", "utf-8") as xml:
    xml.write(xml_content)

方法二:将XML转换为NVARCHAR(MAX)返回

修改SQL语句,将查询结果强制转换为NVARCHAR(MAX)类型,避免LOB处理问题:

SELECT CAST(
(
    SELECT 
      C.BLKODU AS "BLKODU", 
      C.CARIKODU AS "CARIKODU", 
      C.TICARI_UNVANI AS "TICARI_UNVANI", 
      C.ADI_SOYADI AS "ADI_SOYADI", 
      C.VERGI_NO AS "VERGI_NO", 
      C.TC_KIMLIK_NO AS "TC_KIMLIK_NO", 
      C.VERGI_DAIRESI AS "VERGI_DAIRESI", 
      C.CEP_TEL AS "CEP_TEL", 
      C.ILI AS "ILI", 
      C.ILCESI AS "ILCESI", 
      C.ADRESI_1 AS "ADRESI", 
      (SELECT 
          CHR.BLKODU AS "BLKODU", 
          CHR.EVRAK_NO AS "EVRAK_NO", 
          CHR.MAKBUZNO AS "MAKBUZ_NO", 
          CAST(CHR.TARIHI AS DATE) AS "TARIHI", 
          CAST(CHR.VADESI AS DATE) AS "VADESI",  
          CHR.MUH_DURUM AS "MUH_DURUM", 
          CAST(CHR.KPB_ATUT AS DECIMAL(10, 2)) AS "KPB_ATUT", 
          CAST(CHR.KPB_BTUT AS DECIMAL(10, 2)) AS "KPB_BTUT" 
       FROM CARIHR AS CHR 
       WHERE CHR.BLCRKODU = C.BLKODU 
       ORDER BY CHR.TARIHI
       FOR XML PATH('CARIHR'), TYPE) 
    FROM CARI AS C 
    WHERE C.CARIKODU = 'CR00001'
    FOR XML PATH ('CARI')
) AS NVARCHAR(MAX))

之后使用原Python代码即可获取完整字符串内容。


内容的提问来源于stack exchange,提问作者exeen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 00:46:01