为什么我的 VARCHAR 被截断为 255 个字符?我该如何解决?
Why is my VARCHAR truncated to 255 characters? How do I fix this?
设置:
我正在使用以下组件:
- unixODBC 2.3.4
- FreeTDS 1.12
- Python3.6
- SQL炼金术
...针对 MSSQL Server 2014.
问题:
假设我有一个 table 仅包含 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。所以提供的解决方案没有解决问题。
unixODBC/FreeTDS results truncated to 255 character
该线程中未提供解决方案。
关于这一点,应该注意我的字符串通常可以超过 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 个字符长的字符串。
所以总结一下:
- 创建不是在将内容写入数据库时引起的,而是在从数据库中查询内容时字符被静默截断。
- 我只在使用 SQLAlchemy 操作时遇到截断问题。
我不知道为什么我只在使用 SQLAlchemy 查询时收到此错误。有谁知道原因吗?我该如何解决这个问题? (我知道解决方法是使用直接 sql 查询...)
在我的例子中,事实证明有几个复合错误,我列出来以防其他人 运行 遇到与我相同的问题:
- 当我最初创建 table 时,我没有将 table 声明为 VARCHAR(MAX),而是将它们声明为 VARCHAR(8000)。
- 当我修复数据库中的数据table时,我没有更改ORM。该字段仍然是 VARCHAR(8000)。不知何故,这导致了沉默的 t运行cation。
即使将 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
这已将 t运行cation 限制增加到 4096 个字符,但没有解决它。
我试图在这里破译以下答案:
SQLAlchemy Truncating VARCHAR(MAX)
不幸的是,更改文本大小缓冲区不会删除 4096 的 t运行 阳离子限制。在我的情况下,我还必须在查询数据库之前使用来自 SQLAlchemy 的 sql 语句:
db_s.execute('Set TEXTSIZE {0}'.format(SOME_BIG_NUMBER_LIKE_20000)
感谢老post
我的解决方案是在 SELECT 语句中使用 CAST(FIELDNAME as NVARCHAR(4000))
如果我使用CAST(FIELDNAME as NVARCHAR)
,SQLAlchemy 将剪切字符串
设置:
我正在使用以下组件:
- unixODBC 2.3.4
- FreeTDS 1.12
- Python3.6
- SQL炼金术
...针对 MSSQL Server 2014.
问题:
假设我有一个 table 仅包含 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。所以提供的解决方案没有解决问题。
unixODBC/FreeTDS results truncated to 255 character
该线程中未提供解决方案。
关于这一点,应该注意我的字符串通常可以超过 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 个字符长的字符串。
所以总结一下:
- 创建不是在将内容写入数据库时引起的,而是在从数据库中查询内容时字符被静默截断。
- 我只在使用 SQLAlchemy 操作时遇到截断问题。
我不知道为什么我只在使用 SQLAlchemy 查询时收到此错误。有谁知道原因吗?我该如何解决这个问题? (我知道解决方法是使用直接 sql 查询...)
在我的例子中,事实证明有几个复合错误,我列出来以防其他人 运行 遇到与我相同的问题:
- 当我最初创建 table 时,我没有将 table 声明为 VARCHAR(MAX),而是将它们声明为 VARCHAR(8000)。
- 当我修复数据库中的数据table时,我没有更改ORM。该字段仍然是 VARCHAR(8000)。不知何故,这导致了沉默的 t运行cation。
即使将 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
这已将 t运行cation 限制增加到 4096 个字符,但没有解决它。
我试图在这里破译以下答案:
SQLAlchemy Truncating VARCHAR(MAX)
不幸的是,更改文本大小缓冲区不会删除 4096 的 t运行 阳离子限制。在我的情况下,我还必须在查询数据库之前使用来自 SQLAlchemy 的 sql 语句:
db_s.execute('Set TEXTSIZE {0}'.format(SOME_BIG_NUMBER_LIKE_20000)
感谢老post
我的解决方案是在 SELECT 语句中使用 CAST(FIELDNAME as NVARCHAR(4000))
如果我使用CAST(FIELDNAME as NVARCHAR)
,SQLAlchemy 将剪切字符串