Backend - ORM 的原生SQL

发布于:2024-04-11 ⋅ 阅读:(177) ⋅ 点赞:(0)

目录

一、基本认识

(一)意义

(二)原生SQL和SQL

(三)原生SQL的执行方式

1. 直接执行自定义SQL

2. 其他方式

二、SQL 写法

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

(二)元组的形式

三、应用(postgreSQL查询)

(一)基本应用 

1. 连接postgreSQL数据库

2. 执行查询

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

1. where 1=0

2. CASE…THEN 1 ELSE 0 

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 中的表,最好用双引号包裹

# 正确写法
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

(二)元组的形式

列表包元组:

# 正确写法
[('2F0001',), ('2F0002',)]

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

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

三、应用(postgreSQL查询)

(一)基本应用 

1. 连接postgreSQL数据库

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

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

2. 执行查询

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。

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。


网站公告

今日签到

点亮在社区的每一天
去签到