使用 Django 2.X 和 Pyodbc 驱动程序(从 anaconda conda-forge django-pyodbc-azure
安装)对抗 MS Sql Server(不确定哪个版本),我经常在使用 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 版本、驱动程序和 DB)的许多不同情况下,此错误经常发生在我身上,这不是一次性的烦恼。这是我的错还是SQL Server或Pyodbc(或Django)的问题?有没有办法解决错误,而不必一次获取每个obj.otherormtype_set
?
在后台,prefetch_related
功能使用IN (...large number of IDs)
查询来检索对象,这似乎是您正在使用的django-pyodbc-azure
包的已知问题。
您可以找到有关软件包本身的Github问题的更多详细信息。
- https://github.com/michiya/django-pyodbc-azure/issues/101
- https://github.com/michiya/django-pyodbc-azure/issues/143
从快速调查来看,.features.max_query_params
似乎需要调整,这就是我建议做的。
看起来在允许的参数数量方面,这可能是类似于SQLite的限制。