postgresql Django ORM原始删除查询未删除记录

ttcibm8c  于 2023-01-05  发布在  PostgreSQL
关注(0)|答案(2)|浏览(327)

我使用 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 中缺少了什么呢?

uqzxnwby

uqzxnwby1#

一个**.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手册规定你应该使用光标[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被正确地实现,那么我们就不需要担心这个问题。

uqdfh47h

uqdfh47h2#

试试这个:

from django.db import connection
def executeQuery(self, sql, params=[]):
    with connection.cursor() as cursor:
        cursor.execute(
            sql,
            params
        )

像这样使用它:

executeQuery("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])

相关问题