【问题标题】:Some Python requests are being truncated when saving to SQL保存到 SQL 时,一些 Python 请求被截断
【发布时间】:2022-01-06 03:46:38
【问题描述】:

我有一个脚本,用于存储从各种网站请求的 XML(另存为 str's)。即使 SQL 列类型为NVARCHAR(MAX),其中一些请求也会被截断。我需要知道为什么。我不确定这是时间问题(响应在完成下载之前存储到 SQL)还是分页(?)问题。

问题出现在大约 62k 到 65k 字符及以上。低于此字符数的任何内容都会正确保存。

代码:

import urllib.error
import urllib.request
from bs4 import BeautifulSoup

def get_feed(url):
    try:
        header = {'User-Agent': 'Mozilla/5.0'}
        request = urllib.request.Request(url=url, headers=header)
        response = urllib.request.urlopen(request)
        xml = BeautifulSoup(response, 'xml')
        return xml
        
    except urllib.error.HTTPError as response:
        return None


def get_sql_connection():
    try:
        server = 'mydb.database.windows.net'
        database = 'mydb'
        driver= '{ODBC Driver 17 for SQL Server}'
        conn_string = 'DRIVER=' + driver + ';SERVER=' + server + ';DATABASE=' + database
        conn = pyodbc.connect(conn_string + ';Authentication=ActiveDirectoryMsi')
        return conn
    except Exception as e:
        logging.error(e)
        return None


def write_xml(conn, xml):
    end_format = '%Y-%m-%dT%H:%M:%S%z'
    cursor = conn.cursor()
    data = {
        "xml_doc": str(xml),
        "created": datetime.now(timezone(timedelta(hours=-8))).strftime(end_format)}
    cursor.execute("INSERT INTO dbo.XML (xml_doc, created) VALUES (?,?)", data['xml_doc'], data['created'])
    conn.commit()

#-------------------------

conn = get_sql_connection()

url = 'https://example.com'

xml = get_feed(url)

write = write_feed_table(conn, xml)

再次...超过 ~62k-65k 的字符数,xml 将被截断。

【问题讨论】:

  • 你如何确认它们被截断了?通过从 SSMS 中选择数据?它的输出限制为 65,535 个字符,因此请确保您没有被您的工具愚弄,并检查存储的列值的 DATALENGTH()。 (如果数据真的被截断 on write 那么它不会是因为它“在完成下载之前存储” - 但您的驱动程序可能代表您执行一些 SET TEXTSIZE 限制,也许尝试发出SET TEXTSIZE <2 billion>; 在您的查询之前。)
  • 哇,你知道吗.. 我从 SSMS 中选择数据(选择列,然后是 Copy)。我打赌就是这样!疯狂的字符数指向它!我会验证的。谢谢!
  • 确认!这就是问题所在。

标签: python sql sql-server xml


【解决方案1】:

64K 是一种神奇的数字,尤其是对于 XML,但一些提供商和其他软件也会代表您发出短 SET TEXTSIZE commands(例如 32K 或 64K)。您可以使用以下命令覆盖它:

SET TEXTSIZE -1;

但是,通常情况下,当人们说他们的文本被截断为 64K 时,实际情况并非如此,他们只是相信 UI 向他们显示的内容。可以肯定的是,不要测量 UI 的输出,检查源代码!

SELECT DATALENGTH(large_column) FROM dbo.table WHERE <this row>;

我怀疑您将 XML 数据存储在非 XML 列中(或将其转换为输出字符串),并且您正在从 SSMS 中的网格输出复制结果,然后测量该字符串的长度。这会让您认为存储的数据无效,但事实并非如此。默认情况下,您只是网格最大输出的受害者:

你可以增加这个数字,但我承认我没怎么玩过它。特别是对于 XML(和sometimes even not for XML),最好将输出显示为适当的 XML 列。这使它成为网格中的一个可单击单元格,当您单击时,它会打开一个不会像文本输出那样被截断的文档(好吧,除非您超过默认的最大值 2 MB,您也可以将其增加到 5MB,或者,如果你真的很勇敢,无限)。

有关其他一些可能的解决方法,请参阅:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    相关资源
    最近更新 更多