Sql server 无法使用pyodbc在Django中加载文本字段长度超过19455个字符的记录

Sql server 无法使用pyodbc在Django中加载文本字段长度超过19455个字符的记录,sql-server,django,pyodbc,django-pyodbc,Sql Server,Django,Pyodbc,Django Pyodbc,我有一个类似这样的注释模型,它是从一个遗留的MS SQL Server数据库中提取的,因此大多数记录不是由Django创建的: class Note(models.Model): id = models.AutoField(primary_key=True, db_column="note_id") content = models.TextField(db_column="note_content", blank=True, null=True) date_create

我有一个类似这样的注释模型,它是从一个遗留的MS SQL Server数据库中提取的,因此大多数记录不是由Django创建的:

class Note(models.Model):
    id = models.AutoField(primary_key=True, db_column="note_id")
    content = models.TextField(db_column="note_content", blank=True, null=True)
    date_created = models.DateTimeField(db_column="date_created", auto_now_add=True)
    date_modified = models.DateTimeField(db_column="date_modified", null=True, blank=True)
    date_removed = models.DateTimeField(db_column="date_deleted", null=True, blank=True)
对某些记录运行.get会返回DoesNotExist,即使它们存在于数据库中

当MS SQL Server文本中的内容长度(如中的CREATE TABLE Foo content TEXT null字段)超过一定数量时,就会发生这种情况;特别是19455个字符

下面是它在运行中的样子:

>>> note = Note.objects.get(pk=1)
>>> note.content = "x" * 19455
>>> note.save()
>>> note = Note.objects.get(pk=1)
>>> note.content = "x" * 19456
>>> note.save()
>>> note = Note.objects.get(pk=1)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/path/to/django/db/models/query.py", line 366, in get
    % self.model._meta.object_name)
DoesNotExist: Note matching query does not exist.
因此,只要我们尝试检索一个TEXTSIZE设置为大于19456的数字的记录,就不会返回任何记录。您会注意到字符串的最后10个字符与上面的字符串相匹配,减去因为太短而遗漏的字符。例如,对于最后找到的记录,最后10个字符是MGVGSxMfJ2。它缺少真实记录中的T,因为19455的TEXTSIZE比所讨论的字段长度少一个

所以现在我当然想知道,到底发生了什么???我是否可以做进一步的故障排除来确定这是django pyodbc、pyodbc还是FreeTDS的问题?它也可能是SQL Server,但直接在Server Management Studio中运行SET-TEXTSIZE 19456,从[Notes]中选择[Notes].[Notes\u id],[Notes].[Notes\u content],其中[Notes].[Notes\u id]=1,似乎可以正常工作并返回正确的字符数

另请注意,保存工作:


SQL Server和其他组件的版本是什么?表中的数据类型是什么;它是文本还是NVARCHARMAX或者其他什么?您是否使用SQL事件探查器检查发送到服务器的SQL是否真的符合您的预期?它是文本。我将研究如何使用SQL Profiler,看看这是否能为我提供更多信息。我发现了一个修复方法,即将文本字段转换为NVARCHAR字段。它100%地解决了问题,但显然不太理想,因为它意味着检查所有表的模式并更改它们。嗯,这不是一个坏的修复,因为文本是无论如何。是的,我正在这样做,但我对此不满意。
>>> for xx in xrange(19450, 19460):
...     cursor = connection.cursor()
...     try:
...         qrys = 'SET TEXTSIZE %d SELECT [Notes].[note_id], [Notes].[note_content] FROM [Notes] WHERE [Notes].[note_id] = 1' % xx
...         print qrys
...         qry = cursor.execute(qrys)
...         record = qry.fetchone()
...         if record:
...             record_id, record_content = record
...             print record_id, len(record_content), record_content[-10:]
...         else:
...             print "No record found after TEXTSIZE set to %d" % xx
...             break
...     except Exception, inst:
...         print "Error: %s (%s)" % (inst, type(inst))
...         break
...     finally:
...         cursor.close()
... 
SET TEXTSIZE 19450 SELECT [Notes].[note_id], [Notes].[note_content] FROM [Notes] WHERE [Notes].[note_id] = 1
1 19450 VLZapMGVGS
SET TEXTSIZE 19451 SELECT [Notes].[note_id], [Notes].[note_content] FROM [Notes] WHERE [Notes].[note_id] = 1
1 19451 LZapMGVGSx
SET TEXTSIZE 19452 SELECT [Notes].[note_id], [Notes].[note_content] FROM [Notes] WHERE [Notes].[note_id] = 1
1 19452 ZapMGVGSxM
SET TEXTSIZE 19453 SELECT [Notes].[note_id], [Notes].[note_content] FROM [Notes] WHERE [Notes].[note_id] = 1
1 19453 apMGVGSxMf
SET TEXTSIZE 19454 SELECT [Notes].[note_id], [Notes].[note_content] FROM [Notes] WHERE [Notes].[note_id] = 1
1 19454 pMGVGSxMfJ
SET TEXTSIZE 19455 SELECT [Notes].[note_id], [Notes].[note_content] FROM [Notes] WHERE [Notes].[note_id] = 1
1 19455 MGVGSxMfJ2
SET TEXTSIZE 19456 SELECT [Notes].[note_id], [Notes].[note_content] FROM [Notes] WHERE [Notes].[note_id] = 1
No record found after TEXTSIZE set to 19456
>>> 
>>> note.content = (note.content * 10)[:65536] # 65536 is max length allowed for TEXT, apparently
>>> len(note.content)
65536
>>> note.save()
>>> cursor = connection.cursor()
>>> qry = cursor.execute( 'SELECT [Notes].[note_id], DATALENGTH([Notes].[note_content]) FROM [Notes] WHERE [Notes].[note_id] = 1')
>>> record = qry.fetchone()
>>> record
(1, 65536)
>>>