[Tech] 簡單粗暴使用SQLAlchemy

一、介紹

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表為例,下面來講解一下如何向其添加記錄:

  1. 實例化新的User對象
assemble_user = User(id = 1, name = 'sweet', pwd = 'abc')
  1. 添加至session
session.add(assemble_user)
  1. 提交保存至數(shù)據(jù)庫
session.commit()
  1. 關(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末届宠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子乘粒,更是在濱河造成了極大的恐慌豌注,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灯萍,死亡現(xiàn)場離奇詭異轧铁,居然都是意外死亡,警方通過查閱死者的電腦和手機旦棉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門齿风,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绑洛,你說我怎么就攤上這事救斑。” “怎么了真屯?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵脸候,是天一觀的道長。 經(jīng)常有香客問我绑蔫,道長运沦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任配深,我火速辦了婚禮携添,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘篓叶。我一直安慰自己烈掠,他們只是感情好羞秤,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著向叉,像睡著了一般锥腻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上母谎,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天瘦黑,我揣著相機與錄音,去河邊找鬼奇唤。 笑死幸斥,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咬扇。 我是一名探鬼主播甲葬,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼懈贺!你這毒婦竟也來了经窖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤梭灿,失蹤者是張志新(化名)和其女友劉穎画侣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體堡妒,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡配乱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了皮迟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搬泥。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖伏尼,靈堂內(nèi)的尸體忽然破棺而出忿檩,到底是詐尸還是另有隱情,我是刑警寧澤爆阶,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布休溶,位于F島的核電站,受9級特大地震影響扰她,放射性物質(zhì)發(fā)生泄漏兽掰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一徒役、第九天 我趴在偏房一處隱蔽的房頂上張望孽尽。 院中可真熱鬧,春花似錦忧勿、人聲如沸杉女。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熏挎。三九已至速勇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坎拐,已是汗流浹背烦磁。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哼勇,地道東北人都伪。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像积担,于是被迫代替她去往敵國和親陨晶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容