为了方便起见,我正在使用 raw_sql 查询,以便使数据库最小化。我正在删除多余的记录。通过该查询
#d is from a loop and has values
res=MyModel.objects.raw("DELETE FROM mydb_mymodel WHERE mydb_mymodel.s_type = '%s' and mydb_mymodel.barcode = '%s' and mydb_mymodel.shopcode = '%s' and mydb_mymodel.date = '%s'" ,[d.s_type,d.barcode,d.shopcode,d.date])
它不是删除数据库中的记录,而是
当我执行res.query
并从postgres
控制台运行它时,它将起作用!
是的,我可以使用
MyModel.objects.filter(s_type=d.s_type,barcode=d.barcode,
shopcode=d.shopcode,date=d.date).delete()
但是我在 raw_sql 中缺少什么?
答案 0 :(得分:4)
.raw(..)
不会急于执行,就像大多数Django ORM查询是懒惰地执行一样。因此,它返回一个RawQuerySet
对象,并在对象中进行查询。例如:
>>> User.objects.raw('BLA BLA BLA', [])
<RawQuerySet: BLA BLA BLA>
诸如BLA BLA BLA
之类的查询没有任何意义:数据库将在其上出错,但仍然可以检索到RawQuerySet
。
您可以通过例如迭代评估来强制评估,然后我们得到:
>>> list(User.objects.raw('BLA BLA BLA', []))
Traceback (most recent call last):
File "/djangotest/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/djangotest/env/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 71, in execute
return self.cursor.execute(query, args)
File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 250, in execute
self.errorhandler(self, exc, value)
File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
raise errorvalue
File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 247, in execute
res = self._query(query)
File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 412, in _query
rowcount = self._do_query(q)
File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 375, in _do_query
db.query(q)
File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/connections.py", line 276, in query
_mysql.connection.query(self, query)
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BLA BLA BLA' at line 1")
因此list(..)
会强制求值,现在数据库当然会产生错误。但是,即使这是有效的 DELETE
查询,它仍然会引发错误,因为此类查询不会返回任何记录。
为了进行DELETE
调用,Django手册指定您应该use a cursor [Django-doc]:
from django.db import connection
with connection.cursor() as cursor:
cursor.execute(
"DELETE FROM mydb_mymodel WHERE s_type = '%s' AND barcode = '%s' AND shopcode = '%s' AND date = '%s'" ,
[d.s_type,d.barcode,d.shopcode,d.date]
)
但是我认为指定它可能要简单得多:
MyModel.objects.filter(
s_type=d.s_type,
barcode=d.barcode,
shopcode=d.shopcode,
date=d.date
).delete()
这将构造一个DELETE
查询,并正确地序列化参数。一个.delete()
查询很急切,因此犯上述错误的几率要低得多:如果ORM正确实现,那么我们就不必担心。