創用 CC 授權條款
除非另有註明,本網站的著作Fygul Hether製作,以創用CC 姓名標示-非商業性-禁止改作 4.0 國際 授權條款釋出。

2017年12月29日 星期五

SQLAlchemy: Python SQL toolkit and Object Relational Mapper

在使用了Python之後,最先採用的資料庫是SQLite,Python標準庫的sqlite3提供了SQLite資料庫界面,使用上算相當方便,效率也不差。但為了方便將來轉換到PostgreSQL,漸採用SQLAlchemy,它是Python用的SQL工具與ORM (Object Relational Mapper)[1] 。

採用ORM連結資料庫有個好處是,所做的程式在往後若採用不同的資料庫軟體時,資料庫的連結方式無需做大幅度調整。SQLAlchemy支援了多種主流的關聯式資料庫。

雖然SQLAlchemy有相當好處,這裡還是要提醒一點,當資料量很大時,透過ORM存取資料的效率通常不像使用專用資料庫API來的好,譬如前述的SQLite資料庫為例,從sqlite3換成SQLAlchemy後在一次處理大量資料時就會感覺到效率上有點差異。 一般前端應用上的作法通常也不會寫成讓使用者一次調用大量資料, 這類一次調用大量資料的情景,通常像在後端做轉換或匯出/匯入資料,而此時可能會想用其他較合適的方式了。

以下用簡單的例子粗淺的介紹SQLAlchemy的入門使用方式。

架構圖

SQLAlchemy的官方文件[2]的概觀介紹中有個架構圖:
主要分SQLAlchemy ORM與SQLAlchemy Core兩大部分,以下以SQLAlchemy ORM為主,而資料欄位型態則屬SQLAlchemy Core範疇。

ORM: Object Relational Mapper,物件關係對映器

在Python中以SQLAlchemy ORM方式連線資料庫時的3個基本主要部分:
  1. Table:代表資料庫的資料表
  2. 定義與資料表對映的Python物件的類別
  3. mapper:用來對映連結上述1, 2項

宣告對映

SQLAlchemy的declarative可達成上述工作,一個簡單的範例代碼如下,因為在第二個範例會用到它,所以將它存到db_declarative.py:

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

# 宣告對映
Base = declarative_base()


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String(60), nullable=False)


# 連結SQLite3資料庫example.db
engine = create_engine('sqlite:///example.db')

# 建立Schema
Base.metadata.create_all(engine)    # 相當於Create Table

以上定義了一個User類別以對映到user資料表格,最後把資料庫中的資料表建立好。

在實際應用中,這類宣告資料對映的代碼通常會放在稱為models.py的檔案中。這裡的作法略有不同,純粹只是為了方便說明。

新增、查詢

新增、查詢的操作要透過Session,範例代碼example.py:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from db_declarative import Base, User

# 連結到之前建立的資料庫
engine = create_engine('sqlite:///example.db')
Base.metadata.bind = engine

# 建立Session
DBSession = sessionmaker(bind=engine)
# 或是分成二段的寫法。這是用在暫時尚無設定engine,待有engine時在第二段連結到engine
# DBSession = sessionmaker()
# DBSession.bind = engine  # 或是 DBSession.configure(bind=engine)
session = DBSession()

# 建立一對映類別的實例
new_user = User(name='Fygul Hether')

# 新增new_user
session.add(new_user)
session.commit()    # 寫入。在commit()之前,也可rollback()

# 查詢
user = session.query(User).first()
print(user.name)

# 還有其他種查詢的方法:
# session.query(User).all()
# session.query(User).filter(User.id == 1).one()

注意一下上述在sqlalchemy中import的項目與位置,這些最基本的項目可簡單的記下;也可從sqlalchemy的package目錄看出,或利用dir()找一下。

以上是很粗淺的使用,詳情可見官方文件。

SQLAlchemy的更新可算相當頻繁,寫本文的草稿時發現1.2.0版剛釋出不久,前一版1.1.15則在上個月釋出。

參考

[1] https://en.wikipedia.org/wiki/Object-relational_mapping
[2] http://docs.sqlalchemy.org

沒有留言:

張貼留言