繁体   English   中英

为什么我的 VARCHAR 被截断为 255 个字符? 我该如何解决这个问题?

[英]Why is my VARCHAR truncated to 255 characters? How do I fix this?

设置:

我正在使用以下组件:

  • UnixODBC 2.3.4
  • FreeTDS 1.12
  • 蟒蛇 3.6
  • SQLAlchemy

...针对 MSSQL Server 2014。

问题:

假设我有一个只包含 2 列的表格:

  • id(主键,整数)
  • my_text (VARCHAR())

我的 SQLAlchemy 模型如下所示:

from sqlalchemy.dialects.mssql.base import VARCHAR

MyText(Base):
    id = Column(Integer, primary_key=True)
    my_text = Column(VARCHAR())

当我尝试像这样创建一个新的文本条目并且我的文本长度超过 255 个字符时,该字符串会在 255 处以静默方式截断。

my_text='REALLY LONG STRING THAT IS LONGER THAN 255. E.g.: 6000+ characters. Assume my string is 558 bp long.'
print(len(my_text))  # Gives 558 bp.
new_text = MyText(my_text=my_text)
print(len(new_text.my_text))  # Gives 558 bp.
db_s.add(new_text)
print(len(new_text.my_text))  # Gives 558 bp.
db_s.commit()
print(len(new_text.my_text))  # Gives 255 bp now after commit.

起初,我认为这是在写入数据库时​​引起的。 但我发现这是在查询时引起的(请阅读下文)。

问题:

1.) 为什么会这样?

我认为这与驱动程序(例如:unixodbc 2.3.4、FreeTDS 1.12)有关,但我并不完全是在发生这种情况的地方。

2.) 更重要的是,我该如何解决这个问题?

这些问题是相关但不同的:

MySQL VARCHAR 索引在迁移期间被截断为 255

上面的问题是我没有使用MYSQL。 所以提供的解决方案不能解决问题。

unixODBC/FreeTDS 结果被截断为 255 个字符

该线程中没有提供解决方案。

关于这一点,应该注意的是,我的字符串通常可以超过 6000 个字符(因为我正在处理长 DNA 序列)。 我真的很感激任何解决截断问题的方法。

更新 (2017-10-12):

从昨天开始,我做出了一些非凡但同样令人费解的发现。

# Connecting via pyodbc direct connection using just some helper functions to make things more convenient.
con_str = create_connection_string(DATABASE='test')
cur = make_connection_db(connection_str=con_str)
for row in cur.execute('SELECT Text.my_text, len(Text.my_text) FROM [test].[dbo].[Text]'):
    print(row)
    print(len(row[0]))

这给了我一个 558 个字符长的字符串(见下文)。

 ('ATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATG', 
 558)
 558

现在使用 SQL Alchemy 但仍然直接使用 sql 语句。

# Using SqlAlchemy connection with direct SQL query.
eoi_engine = create_engine(
"mssql+pyodbc://user:somepw@db:1234/test?driver=FreeTDS")
s_con = eoi_engine.connect()
s_res = s_con.execute('SELECT Text.my_text, len(Text.my_text) FROM [test].[dbo].[Text]')
for row in s_res:
    print(row)
    print(len(row[0])

这给了我一个字符串,它声称它有 558 个字符长,但实际上它只有 255 个字符长。

 ('ATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATGATG', 
 558)
 255

最后一个场景:

# Using SQLAlchemy full-stack.
Session = sessionmaker()

s = Session(bind=s_con)
fs_res = s.query(DNAPtsSeq).filter().all()
for row in fs_res:
    print(row)
    print(len(row.nt_seq))

这给了我一个只有 255 个字符长的字符串。

所以总结一下:

  • 创建不是在向 DB 写入内容时引起的,而是在从 DB 字符查询内容时被静默截断时引起的。
  • 当我使用 SQLAlchemy 操作时,我只会遇到这个截断问题。

我不知道为什么我只在使用 SQLAlchemy 查询时收到此错误。 有谁知道原因? 我该如何解决这种行为? (我知道解决方法是使用直接 sql 查询...)

就我而言,事实证明存在几个复合错误,我将列出以供后代使用,以防其他人遇到与我相同的问题:

  1. 当我最初创建表时,我没有将表声明为 VARCHAR(MAX),而是将它们声明为 VARCHAR(8000)。
  2. 我在修复数据库中的数据表时,并没有更改ORM。 该字段仍然是 VARCHAR(8000)。 不知何故,这会导致无声截断。
  3. 即使将 VARCHAR(8000) 更改为 VARCHAR() 也不能解决我的问题。 事实证明,MSSQL VARCHAR(MAX) 是高度非标准的。 一个模糊的参考,让我发现有一个不同的 VARCHAR 只用于 MSSQL。 如果您从以下位置导入 VARCHAR:

     from sqlalchemy.dialects.mssql.base import VARCHAR

...然后您可以将您的文本字段声明为 VARCHAR() ,它等于 MSSQL 中的 VARCHAR(Max) 。

http://docs.sqlalchemy.org/en/latest/dialects/mssql.html

这将截断限制增加到 4096 个字符,但没有解决。

我试图在这里破译以下答案:

SQLAlchemy 截断 VARCHAR(MAX)

不幸的是,更改文本大小缓冲区并没有消除 4096 的截断限制。在我的情况下,我还必须在查询数据库之前使用 SQLAlchemy 的 sql 语句:

db_s.execute('Set TEXTSIZE {0}'.format(SOME_BIG_NUMBER_LIKE_20000)

谢谢你的旧帖子

我的解决方案是在 SELECT 语句中使用CAST(FIELDNAME as NVARCHAR(4000))

如果我使用CAST(FIELDNAME as NVARCHAR) ,SQLAlchemy 将剪切字符串

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM