Django执行超长SQL语句的方式

在实际工作SQL语句中,使用到LEFT JOININNER JOIN这种拼接语句是一个很常见的事儿,往往这种语句也很长,我昨天就写了一个80多行的一个语句。但是要知道Django的ORM语法跟Mysql的不一样,但是要在views.py里转用Django的写法来改写一个有join而且超长的语句就很麻烦,而且后期维护起来也很难。

那么遇到这种问题,一般有两种方式解决。

RAW方式

Manager.raw()方式,也就是说:

1
2
3
4
5
from naxxramas.models import AAA	# 假设有AAA这么一个models.py里的类做数据库结构
context["domains"] = AAA.objects.raw(
select * from XXX
#你的SQL语句直接粘贴过来就行,长语句的话,请搭配三个单引号使用
)

但是要注意,这个方法要求查询的时候必须要带primary key,不然的话会报错django.db.models.query_utils.InvalidQuery: Raw query must include the primary key。但是比如我原表的主键是id,而现在要在原表的基础上求和求差肯定不会select id...,那么这里可以讨个巧,使用SELECT 1 as id,...这样把id带进去但是写死,而在前端的时候,就放弃掉id即可。

使用DB-API方式

这就完全脱离ORM的范围了,直接使用了MySQLbd的api,举个例子如下:

1
2
3
4
5
6
7
8
9
>>> from django.db import connection
>>> cursor = connection.cursor()
>>> cursor.execute('''SELECT count(*) FROM people_person''')
1L
>>> row = cursor.fetchone()
>>> print row
(12L,)
>>> Person.objects.all().count()
12

其实我不推荐使用这种方式,代码看起来不伦不类的。

最后补充一下,如果要看一下ORM写法对应的sql写法是啥,就用query,举个例子:

1
2
3
4
>>> qs = Department.objects.filter(departmentvolunteer__isnull=True).values_list('name', flat=True)
>>> print(qs.query)
SELECT "app_department"."name" FROM "app_department" LEFT OUTER JOIN
"app_departmentvolunteer" ON ( "app_department"."id" = "app_departmentvolunteer"."department_id" ) WHERE "app_epartmentvolunteer"."id" IS NULL

这样可以帮你排查sql的问题。

参考资料

https://docs.djangoproject.com/zh-hans/3.2/topics/db/sql/
https://www.cnblogs.com/fmgao-technology/p/10119671.html

感谢您请我喝咖啡~O(∩_∩)O,如果要联系请直接发我邮箱chenx1242@163.com,我会回复你的
-------------本文结束感谢您的阅读-------------