一、介紹
SQLAlchemy是Python編程語言下的一款ORM框架舅踪,使用此庫可以便捷的使用python代碼來操作SQL數(shù)據(jù)庫纽甘,下面,我們以MySQL數(shù)據(jù)庫為例抽碌,來介紹一下SQLAlchemy的使用吧悍赢。
二决瞳、連接數(shù)據(jù)庫
在使用pip install SQLAlchemy
安裝SQLAlchemy之后,就可以使用其進行數(shù)據(jù)庫的連接了左权。在這里皮胡,我們使用create_engine
,如下例:
engine = create_engine ('數(shù)據(jù)庫類型+數(shù)據(jù)庫驅(qū)動名稱://用戶名:口令@機器地址:端口號/數(shù)據(jù)庫名’)
例如:
(‘mysql+pymysql://root: password@localhost:3306/test’)
通常在連接完數(shù)據(jù)庫后赏迟,我們會創(chuàng)建Session并綁定上文建立的數(shù)據(jù)庫連接屡贺,之后對數(shù)據(jù)庫的操作都在通過Session對象來完成。
# 首先要導(dǎo)入sessionmaker
from sqlalchemy.orm import sessionmaker
# 創(chuàng)建Session對象來綁定上文建立的engine連接
Session = sessionmaker(bind=engine)
# 實例化Session
session = Session()
之后的增刪查改操作都使用實例化后的session來進行哦
三锌杀、聲明映射
當(dāng)我們使用SQLAlchemy ORM框架連接完數(shù)據(jù)庫后甩栈,接下來的就要將數(shù)據(jù)庫中的表轉(zhuǎn)換為python對象了。一般來說這個環(huán)節(jié)可以有兩種方法:
1. 手動聲明
首先糕再,使用
declarative_base
創(chuàng)建對象基類from sqlalchemy.ext.declarative import declarative_base Base = declarative_base()
創(chuàng)建完對象基類后量没,我們就可以對照數(shù)據(jù)庫定義表對象了
from sqlalchemy import Column, Integer, String class User(Base): # 定義表名 __tablename__ = 'users' # 定義表內(nèi)容 id = Column(Integer, primary_key=True) name = Column(String(20)) score = Column(Integer)
2. 指令聲明
終端一行指令,優(yōu)雅搞定
sqlacodegen mysql+pymysql://用戶名:密碼@機器地址:端口號/數(shù)據(jù)庫名 > 數(shù)據(jù)庫對象存放路徑 例如: sqlacodegen mysql+pymysql://root:password@localhost:3306/test >temp.py 隨后突想,打開temp.py就可以看到生成的數(shù)據(jù)庫對象啦
四殴蹄、插入記錄
以上面的User表為例,下面來講解一下如何向其添加記錄:
- 實例化新的User對象
assemble_user = User(id = 1, name = 'sweet', pwd = 'abc')
- 添加至session
session.add(assemble_user)
- 提交保存至數(shù)據(jù)庫
session.commit()
- 關(guān)閉session
session.close()
提交完成后需要關(guān)閉session斷開數(shù)據(jù)庫連接猾担, 不然數(shù)據(jù)庫會一直連接袭灯,直到程序終止
那么,如何在一個session中批量向數(shù)據(jù)庫添加記錄呢绑嘹?
# 創(chuàng)建一個存放記錄的列表
user_list = []
user_a = User(id = 1, name = 'sweet', score = 87)
user_b = User(id = 2, name = 'candy', score = 91)
user_list.append(user_a, user_b)
# 注意這里要用add_all
session.add_all(user_list)
session.commit()
session.close()
五稽荧、查詢記錄
SQLAlchemy既然是用python來操作數(shù)據(jù)庫,那么對于基本的SQL語句工腋,也能“翻譯”為對應(yīng)的代碼蛤克,下面我們以上面的users表為例,來說一下SQLAlchemy查詢語句的基本用法夷蚊。
· 基本查詢
a. 查詢users表內(nèi)的所有的記錄
SQL語句
SELECT * FROM users;
SQLAlchemy python
session.query(User).all()
Note:
這里需要注意哦构挤,雖然操作的表名為users,但其對應(yīng)的對象名為User惕鼓,所以我們還是以 'User' 來操作表哦筋现;
使用all()查詢出來的結(jié)果是一個list,可以使用list的取值或遍歷方法來對其進行操作箱歧。
b. 查詢users表內(nèi)所有name
SQL語句
SELECT users.name FROM users;
SQLAlchemy python
session.query(User.name).all()
c. 查詢users表內(nèi)name為candy的記錄
SQL語句
SELECT * FROM users WHERE users.name = 'candy';
SQLAlchemy python
session.query(User).filter(User.name == 'candy').all()
Note:
filter的用法類似于SQL語句里的WHERE矾飞,但要注意的是,這里面的等于需要用'=='哦呀邢。
d. 查詢users表內(nèi)id大于2并且name是'sweet'或'candy'的記錄
SQL語句
SELECT * FROM users WHERE users.id > 2 AND users.name IN ('sweet', 'candy');
SQLAlchemy python
session.query(User).filter(User.id > 2, User.name.in_(['sweet'.'candy'])).all()
Note:
這里有兩個"與"條件洒沦,SQLAlchemy的用法是在filter()中用 ',' 作為分割;
而在SQLAlchemy中使用in_(list)的方式來表示字段值在list范圍內(nèi)价淌。
e. 查詢users表內(nèi)name中有'ee'的記錄
SQL語句
SELECT * FROM users WHERE users.name LIKE '%ee%';
SQLAlchemy python
session.query(User).filter(User.name.like('%ee%')).all()
f. 查詢users表內(nèi)id為1或name以's'開頭的記錄
SQL語句
SELECT * FROM users WHERE users.name LIKE 's%' OR users.id = 1;
SQLAlchemy python
session.query(User).filter(or_(User.name.like('s%'), User.id == 1)).all()
g. 根據(jù)id倒序查詢users表內(nèi)的記錄
SQL語句
SELECT * FROM users ORDER BY users.id DESC;
SQLAlchemy python
session.query(User).order_by(User.id.desc())
Note:
GROUP_BY使用方式與其類似申眼,不做贅述瞒津;
asc使用方式與其類似,不做贅述括尸。
以上的查詢已經(jīng)可以覆蓋80%的業(yè)務(wù)需求了巷蚪,但SQLAlchemy的使用還遠遠不止這些,下面就來介紹一下SQLAlchemy的高級運用吧濒翻。
· 多表聯(lián)合查詢
可以使用filter語句來進行多表關(guān)聯(lián)
session.query(User, Address).filter(User.id==Address.user_id)\ .filter(Address.city=='sh')>.all()
也可以簡單粗暴使用join()
session.query(User).join(Address)\ .filter(Address.city=='sh').all()
· 函數(shù)計算
a. 查詢users表內(nèi)的總分數(shù)
SQL語句
SELECT SUM(score) FROM users;
SQLAlchemy python
session.query(sqlalchemy.func.sum(score)).scalar()
b. 查詢users表內(nèi)分數(shù)大于90的個數(shù)
SQL語句
SELECT COUNT(score) FROM users WHERE users.score > 80;
SQLAlchemy python
session.query(sqlalchemy.func.avg(User.score)).filter(User.score>80).scalar()
Note:
一般來說屁柏,不太會使用fun.count()這個函數(shù),因為可以取出數(shù)據(jù)記錄列表后利用python的len()來計算長度有送。
· 語義化用法
翻譯成“語義化”用法不知妥不妥當(dāng)淌喻,原文是"Textual SQL"。這里的意思就是將SQL語句直接寫入python代碼中雀摘,如下例:
使用param()來傳參
session.query(User).filter(text("id<:value")).params(value=2).one()
簡單粗暴execute()執(zhí)行SQL語句
session.execute(text('SELECT * FROM users WHERE id = :value'), ({'value': 1})).one()
或者醬紫用from_statement
stmt = text("SELECT name, id, fullname, password FROM users where name=:name") session.query(User).from_statement(stmt).params(name='sweet').all()
六似嗤、刪除記錄
簡單粗暴上栗子:
session.query(User).filter(User.name=='sweet').delete()
如果查詢條件里有in_,需要在delete()中加如下參數(shù):
session.query(User).filter(User.in_(['sweet'])).delete(synchronize_session='fetch')
補充
最近發(fā)現(xiàn)更新一條記錄的騷操作
def update_tg_case(session, params):
try:
record = session.query(TgCase).filter(TgCase.id == params.get('id')).one()
update_obj = tg_case(params)
if record:
for key in update_obj.__dict__:
if key == '__sa_instance_state':
continue
setattr(record, key, getattr(update_obj, key))
session.flush()
return True
except Exception:
session.rollback()
return False