针对SQL Server的Prefetch_related故障

时间:2019-01-02 19:03:10

标签: python sql-server django orm pyodbc

使用针对MS Sql Server(不确定哪个版本)的Django 2.X和Pyodbc驱动程序(从anaconda conda-forge django-pyodbc-azure安装),我经常使用prefetch_related遇到错误。一个例子看起来很像:

for obj in MyORMType.objects.prefetch_related('otherormtype_set').all():
    pass

其中OtherOrmType有一个简单的MyOrmType外键,错误是:

...
/opt/conda/lib/python3.6/site-packages/django/db/backends/utils.py in _execute(self, sql, params, *ignored_wrapper_args)
     83                 return self.cursor.execute(sql)
     84             else:
---> 85                 return self.cursor.execute(sql, params)
     86 
     87     def _executemany(self, sql, param_list, *ignored_wrapper_args):

/opt/conda/lib/python3.6/site-packages/sql_server/pyodbc/base.py in execute(self, sql, params)
    544         self.last_params = params
    545         try:
--> 546             return self.cursor.execute(sql, params)
    547         except Database.Error as e:
    548             self.connection._on_error(e)

ProgrammingError: ('The SQL contains -2098 parameter markers, but 128974 parameters were supplied', 'HY000')

我可以回到愚蠢的水平:

for obj in MyORMType.objects.all():
    other_objs = obj.otherormtype_set.all()

但这显然很慢。在这个特定设置(总是相同的Django版本,驱动程序和数据库)中,在许多不同情况下,我经常会遇到此错误,这不是一个烦人的烦恼。这是我的错还是SQL Server或Pyodbc(或Django)的问题?有没有一种方法可以解决该错误,而不必一次获取每个obj.otherormtype_set

1 个答案:

答案 0 :(得分:1)

prefetch_related功能在内部使用IN (...large number of IDs)查询来检索对象,这似乎与您正在使用的django-pyodbc-azure软件包有关。

您可以在软件包本身的Github问题上找到更多详细信息。

  1. https://github.com/michiya/django-pyodbc-azure/issues/101
  2. https://github.com/michiya/django-pyodbc-azure/issues/143

通过快速调查,似乎需要调整what I suggested doing.features.max_query_params

似乎像SQLite one with regards to number of allowed parameters一样有局限性。