目录
[1. 直接执行自定义SQL](#1. 直接执行自定义SQL)
[2. 其他方式](#2. 其他方式)
[二、SQL 写法](#二、SQL 写法)
[(一)原生SQL 中的表,最好用双引号包裹](#(一)原生SQL 中的表,最好用双引号包裹)
[1. 连接postgreSQL数据库](#1. 连接postgreSQL数据库)
[2. 执行查询](#2. 执行查询)
[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') # 端口号
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。