Backend - ORM 的原生SQL

目录

一、基本认识

(一)意义

(二)原生SQL和SQL

(三)原生SQL的执行方式

[1. 直接执行自定义SQL](#1. 直接执行自定义SQL)

[2. 其他方式](#2. 其他方式)

[二、SQL 写法](#二、SQL 写法)

[(一)原生SQL 中的表,最好用双引号包裹](#(一)原生SQL 中的表,最好用双引号包裹)

(二)元组的形式

三、应用(postgreSQL查询)

(一)基本应用

[1. 连接postgreSQL数据库](#1. 连接postgreSQL数据库)

[2. 执行查询](#2. 执行查询)

(二)利用原生sql(raw方式)替换Q对象查询

[1. where 1=0](#1. where 1=0)

[2. CASE...THEN 1 ELSE 0](#2. CASE…THEN 1 ELSE 0)

[3. CASE...END=1](#3. CASE…END=1)


一、基本认识

(一)意义

针对数据库的查询效率,Django的ORM较低,原生SQL较高。

(二)原生SQL和SQL

原生SQL和SQL是有区别的。

原生SQL语句是Django的写法,不能放进数据库中直接查询。

一般情况下使用ORM的filter、update等方式,方便代码统一调整管理。当ORM实在没有办法实现查询或提高查询效率,则用原生SQL。

(三)原生SQL的执行方式

1. 直接执行自定义SQL

该方式无需模型,直接访问数据库。(直接执行update、insert等语句)

利用 cursor 指针(游标)对象。

2. 其他方式

raw 方式、extra 方式(基本没用)

二、SQL 写法

(一)原生SQL 中的表,最好用双引号包裹

python 复制代码
# 正确写法
insert into "myApp_book" (card, name, author, btype, price, num) values %s 

# 错误写法(会提示该表不存在:relation "myapp_book" does not exist)
insert into myApp_book (card, name, author, btype, price, num) values %s

(二)元组的形式

列表包元组:

python 复制代码
# 正确写法
[('2F0001',), ('2F0002',)]

# 错误写法
[('2F0001'), ('2F0002')]

原因:元组里只有一个数据时,得用逗号结尾

三、应用(postgreSQL查询)

(一)基本应用

1. 连接postgreSQL数据库

python 复制代码
conn = psycopg2.connect(host='XX.XX.XX.XX',  # 主机地址
                        dbname='BookDB',  # 数据库名称
                        user='postgres',  # 用户名
                        password='123456',  # 密码
                        port='5432')  # 端口号

可参考另一篇文章:Backend - python 连接 & 操作 PostgreSQL DB(数据库)-CSDN博客

2. 执行查询

python 复制代码
cur = conn.cursor()  # 创建游标对象
cur.execute('select card from "myApp_book" limit 10')  # 执行SQL语句
res_list = None
res_list = cur.fetchall()  # 获取记录值,结果是列表包元组:[('1F002', '数据结构怎么学'), ('1F001', '数据库原理')]
cols_list = [row[0] for row in cur.description]  # 获取栏位名称['card', 'name']
data_list = [dict(zip(cols_list, val_list)) for val_list in cur.fetchall()]  # 组装列表包字典:data_list [{'card': '1F002', 'name': '数据结构怎么学'}, {'card': '1F001', 'name': '数据库原理'}]

(二)利用原生sql(raw方式)替换Q对象查询

举例:查询 from_dict 字典中,存在于数据库记录所对应的id。

python 复制代码
from myApp.models import model_book
class Query_DB:
    def __raw_sql(self):
        cond = str()
        for dictval in self.from_list:
            cond += (' OR CASE WHEN card = {} ' 
                    ' AND "name" =\'{}\' '
                    ' AND author =\'{}\' '
                    ' AND is_active = {} '
                    ' THEN 1 ELSE 0 END=1 ').format(dictval.get('Card'), dictval.get('Name'),  dictval.get('Author'), dictval.get('Status'))
        return 'SELECT id FROM {} WHERE 1=0 {}'.format('public.\"my_book\" ', cond)
    def query_data(self):
        self.from_list = [{'Card': '1F002', 'Name': '数据结构怎么学', 'Author': '萝卜干', 'Status': True}, {'card': '1F001', 'name': '数据库原理', 'Author': '小星星', 'Status': False}]
        id_qst = model_book.Book.objects.raw(self.__raw_sql)
        id_obj = [i for i in id_qst]  # id_obj=[<Book: Book object (22)>, <Book: Book object (23)>]
    query_data()

1. where 1=0

表示该条件为false,继续判定下一个条件。

2. CASE...THEN 1 ELSE 0

表示该条件是否匹配,若匹配则返回1,否则为0.

3. CASE...END=1

表示该条件下获取的值是否为1,若为1,则结果为true,则查询出ID。

相关推荐
Amd7945 个月前
深入 Django 模型层:数据库设计与 ORM 实践指南
性能优化·数据安全·django orm·模型继承·查询操作·数据库关系·模型设计