SQLAlchemy使用

簡介

SQLAlchemy是Python語言的一款流行的ORM(Object Relational Mapper)框架,該框架創建在數據庫API之上,使用關係對象映射進行數據庫操做,即將對象轉換成SQL,而後使用數據API執行SQL並獲取執行結果。html

安裝SQLAlchemy也很簡單,直接使用pip安裝便可。python

pip install sqlalchemy

下面重點介紹SQLAlchemy的使用。mysql

版本檢查

import sqlalchemy
sqlalchemy.__version__	# 1.1.9

當前sqlalchemy版本爲1.1.9程序員

鏈接數據庫

from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:123456@192.168.110.13:3306/student', echo=True)
  • engine 是 Engine類的一個對象
  • echo=True代表開啓logging模塊的日誌
  • 數據庫鏈接:engine://user:password@host:port/database,其中engine爲mysql+pymysql,或者是mysql+mysqldb,或者是oracle+cx_oracle等等

建立表

from sqlalchemy import create_engine
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base


engine = create_engine('mysql+pymysql://root:123456@192.168.110.13:3306/student', echo=True)
Base = declarative_base()  # 生成Model類的基類

class User1(Base):
    __tablename__ = 'user1'
    
    extend_existing = True
    # 定義三個列
    id = Column(Integer, autoincrement=True, primary_key=True)
    name = Column(String(64), unique=True, nullable=False)
    age  = Column(Integer)
    
        
    def __repr__(self):
        return 'User(id={}, name={}, age={})'.format(self.id, self,name, self.age)
    
    def __str__(self):
        return self.__repr__()
        
Base.metadata.create_all(engine)  # 建立全部表
Base.metadata.drop_all(engine)  # 刪除全部表

# 定義類的實例方法1
u1 = User()	# User類只接收一個位置參數self,和關鍵字參數**kwargs
u1.name = 'aa'  # 給User類的各個列賦值
u1.age=19
print(u1)  # User(id=None, name=aa, age=19)

# 定義類的實例方法2
u2 = User(name='bb', age='123')
print(u2)  # User(id=None, name=bb, age=123)
  • 派生類User會繼承基類Base的初始化函數__init__,會自動的接受咱們所定義的列對應的關鍵字參數
  • 未賦值的列會用None初始化,如上面的id

Session

SQLAlchemy真正處理數據庫的部分是Session。sql

若是已經建立好了一個Engine對象engine,那麼能夠用如下語句建立一個Sessionshell

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)

若是engine爲建立好,則能夠用如下語句建立數據庫

Session = sessionmaker()

當engine建立好以後,在配置Session便可session

Session.configure(bind=engine)

當須要和數據庫交互的時候,就須要實例化Sessionoracle

session = Session()

建立完成以後這個session並無立刻獲取數據庫鏈接。只有當這個session第一次操做數據庫的時候纔會從Engine維護的鏈接池中獲取一個鏈接,並持有這個鏈接一直到咱們提交了全部的改變或者關閉了這個session。app

DML

insert

user = User(name='haha', age='123')
session.add(user)
session.commit()

若是這個commit的過程當中發生異常,則後續全部的commit都沒法執行,所以DML都須要放在try...except中處理,以下

user = User(name='flowsnow', age=18)
session.add(user)
try:
    session.commit()
except Exception as e:
    session.rollback()
    raise e

update

和insert相似,都是使用session.add方法,可是update操做的時候須要數據庫中存在帶操做的記錄。

user.age = 20
session.add(user)
try:
    session.commit()
except Exception as e:
    session.rollback()
    raise e

delete

刪除以前必須確保數據庫中存在要刪除的記錄。

session.delete(user)	# user必須已經存在
try:
    session.commit()
except Exception as e:
    session.rollback()
    raise e

QUERY

for u in session.query(User).filter(User.age < 20).order_by(User.age.desc())[1:3]:
    print(u)

此條語句經ORM轉換以後的SQL以下:

SELECT
	USER.id AS user_id,
	USER.NAME AS user_name,
	USER.age AS user_age
FROM USER
WHERE USER.age < % (age_1) s
ORDER BY USER.age DESC
LIMIT % (param_1) s, % (param_2) s

query函數的返回結果爲一個Query對象,Query對象是可迭代的,支持切片操做。

下面列舉常見的filter操做

  • 相等

    query.filter(User.name == 'suncle')
  • 不相等

    query.filter(User.name != 'suncle')
  • 模糊匹配like:大小寫敏感

    query.filter(User.name.like('%sun%'))
  • 模糊匹配ilike:大小寫不敏感

    query.filter(User.name.ilike('%sun%'))
  • IN

    query.filter(User.name.in_(['suncle', 'abc', 'suncle']))
    
    # 也支持Query對象
    query.filter(User.name.in_(
        session.query(User.name).filter(User.name.like('%sun%'))
    ))
  • NOT IN

    query.filter(~User.name.in_(['ed', 'wendy', 'jack']))
  • IS NULL

    query.filter(User.name == None)
    
    # 上面的寫法不符合pep8規範,IDE會給出提示,能夠用下面的方法替代,pep8的寫法是is None
    query.filter(User.name.is_(None))
  • IS NOT NULL

    query.filter(User.name != None)
    
    # 上面的寫法不符合pep8規範,IDE會給出提示,能夠用下面的方法替代,pep8的寫法是is not None
    query.filter(User.name.isnot(None))
  • AND

    # 方法1:使用and_()方法
    from sqlalchemy import and_
    query.filter(and_(User.name == 'flowsnow', User.age == 18))
    
    # 方法2:filter()支持多個關鍵字參數
    query.filter(User.name == 'flowsnow', User.age == 18)
    
    # 方法3:屢次調用filter函數
    query.filter(User.name == 'flowsnow').filter(User.age == 18)
  • OR

    from sqlalchemy import or_
    query.filter(or_(User.name == 'suncle', User.name == 'flowsnow'))

下面列舉SQL支持的常見的function

from sqlalchemy import func
session.query(func.count(User.id)).first() # count
session.query(func.max(User.age)).first() # max
session.query(func.avg(User.age)).first() # avg

Relationship

表和表之間會有外鍵關係,數據庫的外鍵關係在ORM中的使用方法以下:

from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship

Base = declarative_base()  # 生成Model類的基類

class Author(Base):  # 做者類
    __tablename__ = 'author'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), unique=True, nullable=False)
    
    posts = relationship('Post')
    
    def __repr__(self):
        return 'Author<id={}, name={}>'.format(self.id, self.name)
    
    def __str__(self):
        return self.__repr__()
    
    
class Post(Base):  # 文章類
    __tablename__ = 'post'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(128), nullable=False, index=True)
    content = Column(String(8096), nullable=False)
    author_id = Column(Integer, ForeignKey('author.id'), nullable=False)
    
    author = relationship('Author')
    
    def __repr__(self):
        return 'Post<id={}, title={}>'.format(self.id, self.title)
    
    def __str__(self):
        return self.__repr__()
    

engine = create_engine('mysql+pymysql://root:123456@192.168.110.13:3306/student', echo=True)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# 新增一個做者
author = Author()
author.name = 'flowsnow'
session.add(author)
session.commit()
print(author)  # Author<id=1, name=flowsnow>

# 新增一篇文章
post = Post()
post.title = 'first post'
post.content = 'oihdoshfohro'
post.author = author
session.add(post)
session.commit()
print(author.posts)  # [Post<id=1, title=first post>]

# 再新增一篇文章
post = Post()
post.title = 'second post'
post.content = 'liabhgekegpaerg'
post.author = author
session.add(post)
session.commit()
print(author.posts)  # [Post<id=1, title=first post>, Post<id=2, title=second post>]

數據庫維護數據之間的外鍵關係會消耗數據庫資源,影響性能,在大型的應用中通常不使用外鍵等數據庫高級特性,而是由應用框架來維護數據之間的約束。


參考

  1. 官方文檔-Object Relational Tutorial
  2. A step-by-step SQLAlchemy tutorial
  3. 廖雪峯-使用SQLAlchemy

記得幫我點贊哦!

精心整理了計算機各個方向的從入門、進階、實戰的視頻課程和電子書,按照目錄合理分類,總能找到你須要的學習資料,還在等什麼?快去關注下載吧!!!

resource-introduce

念念不忘,必有迴響,小夥伴們幫我點個贊吧,很是感謝。

我是職場亮哥,YY高級軟件工程師、四年工做經驗,拒絕鹹魚爭當龍頭的斜槓程序員。

聽我說,進步多,程序人生一把梭

若是有幸能幫到你,請幫我點個【贊】,給個關注,若是能順帶評論給個鼓勵,將不勝感激。

職場亮哥文章列表:更多文章

wechat-platform-guide-attention

本人全部文章、回答都與版權保護平臺有合做,著做權歸職場亮哥全部,未經受權,轉載必究!

相關文章
相關標籤/搜索