为django编写sql查询时遇到问题。
如果查询为Books.objects.filter(id=1, name='ABC')
,则使用django.db.connection的sql查询将是:
cur = connection.cursor()
cur.execute('SELECT title FROM book WHERE id = %s AND name = %s',[id, name])
如果名称字段中有值,则此方法有效,但如果名称为None,则返回[]。那么Books.objects.filter(id=1, name=None)
的等效值应该是什么。
将同时包含None和其他值的查询是什么?
cur = connection.cursor()
for id, name in [(1, 'A'),(2, None),(3, 'TEST')]:
cur.execute('????',[id, name])
我想知道是否可以在上面的代码中使用查询代替'????'
。
答案 0 :(得分:2)
将同时包含None和其他值的查询是什么。
Django实际上容纳None
和其他值。如果我们查看生成的查询,它将看起来像:
>>> print(Book.objects.filter(id=4, name=None).query)
SELECT `app_book`.`id`, `app_book`.`name` FROM `app_book` WHERE (`app_book`.`id` = 4 AND `app_book`.`name` IS NULL)
如果您因此在过滤器中传递了None
,那么它将把它转换为IS NULL
。
以及特定字符串:
>>> print(Book.objects.filter(id=4, name='Book name').query)
SELECT `app_book`.`id`, `app_book`.`name` FROM `app_book` WHERE (`app_book`.`id` = 4 AND `app_book`.`name` = Book name)
您可以使用__isnull
lookup [Django-doc]使其更明确:
Book.objects.filter(id=4, name__isnull=True)
在SQL中,您不能通过写NULL
用=
进行检查,原因是:
mysql> select NULL = NULL, NULL is NULL, 'foo' is NULL, 'foo' = NULL;
+-------------+--------------+---------------+--------------+
| NULL = NULL | NULL is NULL | 'foo' is NULL | 'foo' = NULL |
+-------------+--------------+---------------+--------------+
| NULL | 1 | 0 | NULL |
+-------------+--------------+---------------+--------------+
实际上,用NULL
进行检查也会导致NULL
。
我想知道是否会有查询可以代替'????'在上面的代码中
您可以进行更复杂的检查,例如:
cur.execute(
'SELECT title FROM book WHERE id = %s AND (name = %s or (name = %s) is NULL)',
[id, name, name]
)
但这会使它变得更复杂且更难阅读,并且可能会使查询的速度比正确格式化它的速度慢。
如果要选择满足2个元组的所有值,则可以生成如下查询:
from django.db.models import Q
from functools import reduce
from operator import or_
data = [(1, 'A'),(2, None),(3, 'TEST')]
Book.objects.filter(
reduce(or_, [Q(id=id, name=name) for id, name in data])
)