第17次課

python中使用SQLAlchemy

概念簡介

  • ORM
    ORM是Object-Relational Mapping的簡寫。今天學習的SQLAlchemy其實就是ORM框架中最有名的一個。
    SQLAlchemy框架工做
    經過數據的API,使用關係對象映射進行數據庫操做,也就是:將對象轉換成SQL,而後使用數據API執行SQL並獲取執行結果。orm-sqlalchemy-coreorm-sqlalchemy-core
    SQLAlchemy自己沒法操做數據庫,其必須經過pymysql等第三方插件。上圖中Dialect用於和數據API進行交流,根據配置文件的不一樣調用不一樣的數據庫API,從而實現對數據庫的操做。
    1
    2
    3
    4
    5
    6
    7
    8
    # mysqldb
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
    # pymysql
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
    # mysql-connector
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
    # cx_oracle
     oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]

對比

ORM思想的核心是隱藏了數據訪問細節,提供了通用的數據庫交互。而且徹底不用考慮SQL語句,從而快速開發。html

  • 使用SQL建立表
    1
    2
    3
    4
    5
    6
    7
    CREATE TABLE student(
      id int not null auto_increment,
      name varchar(100),
      age int,
      address varchar(100),
      PRIMARY KEY(id)
    )

上述是一個簡單的建立單表的語句。python

  • 使用SQLAlchemy
    方法1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from sqlalchemy import create_engine, Column, String, Integer, MetaData
    from sqlalchemy.ext.declarative import declarative_base
    
    engine = create_engine("mysql+pymysql://root:123456@localhost/test", encoding='UTF-8', echo=True)
    
    Base = declarative_base()    #生成orm基類
    
    class Student(Base):
        __tablename__ = 'student'    #指定表名
        id = Column(Integer, primary_key=True)
        name = Column(String(100))
        age = Column(Integer)
        address = Column(String(100))
    
    Base.metadata.create_all(engine)    #建立表結構

方法2mysql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from sqlalchemy import Table, MetaData, Column, Integer, String, create_engine
from sqlalchemy.orm import mapper

engine = create_engine("mysql+pymysql://root:123456@localhost/test", encoding='UTF-8', echo=True)
metadata = MetaData()

student = Table('student', metadata,
             Column('id', Integer, primary_key=True),
             Column('name', String(100)),
             Column('age', Integer),
             Column('address', String(100))
             )


class Student(object):
    def __init__(self, name, age, address):
        self.name = name
        self.age = age
        self.address = address


mapper(Student, student)    #此處有問題,待解決

 

說明
echo=True 顯示每條執行的SQL語句,能夠關閉。
create_engine()返回一個Engine的實例,而且表示經過數據庫語法處理細節的核心接口,這種狀況下數據庫語法將被解釋成python的類方法。
上面簡單示例對比了下使用SQL直接建立表和使用ORM框架建表的區別,下面開始介紹SQLAlchemy的使用。sql

使用

安裝

經過pip install SQLAlchemy安裝,訪問mysql使用pymysql,安裝方法pip install pumysql。能夠參照python訪問mysql數據庫

插入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from sqlalchemy import create_engine, Column, String, Integer, MetaData
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:123456@localhost/test", encoding='UTF-8', echo=True)
DBsession = sessionmaker(bind=engine) #建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
session = DBsession()    #生成session實例
Base = declarative_base()

class Student(Base):
    __tablename__ = 'student'
    id = Column(Integer, primary_key=True)
    name = Column(String(100))
    age = Column(Integer)
    address = Column(String(100))


student1 = Student(id=1001, name='Alice', age=25, address="anhui")
student2 = Student(id=1002, name='Bob', age=69, address="beijing")
student3 = Student(id=1003, name='Cerry', age=14, address="jiangsu")

session.add_all([student1, student2, student3])
session.commit()
session.close()

查詢

查詢是經過Session的query()方法建立一個查詢對象,這個函數的參數能夠是任何類或者類的描述的集合。
查詢出來的數據是一個對象,直接經過對象的屬性調用。數組

1
2
3
4
5
6
7
8
9
10
11
12
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from db.orm2 import Student

engine = create_engine('mysql+pymysql://root:123456@localhost/test')
DBsession = sessionmaker(bind=engine)
session = DBsession()

a = session.query(Student)
print(a)
for i in a:
    print(i.id, i.name, i.age, i.address)

 

輸出結果session

1
2
3
4
5
SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age, student.address AS student_address 
FROM student
1001 Alice 25 anhui
1002 Bob 69 beijing
1003 Cerry 14 jiangsu

 

session.query(Student)結果爲查詢的SQL語句,若出現查詢結果錯誤能夠經過查看SQL確認。oracle

  • filter()和filter_by()
    過濾條件。==!=like等過濾操做均可以在filter函數中使用。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    from db.orm2 import Student
    
    engine = create_engine('mysql+pymysql://root:123456@localhost/test')
    DBsession = sessionmaker(bind=engine)
    session = DBsession()
    
    a = session.query(Student).filter(Student.id == 1001)
    b = session.query(Student).filter_by(id=1001)
    
    for x in a:
        print(x.id, x.name, x.age, x.address)
    for i in b:
        print(i.id, i.name, i.age, i.address)

輸出結果app

1
2
1001 Alice 25 anhui
1001 Alice 25 anhui

 

filter()filter_by()區別
filter能夠像寫sql的where條件那樣寫>、<等條件,但引用列名時,須要經過類名.屬性名的方式。
filter_by能夠使用python的正常參數傳遞方法傳遞條件,指定列名時,不須要額外指定類名,參數名對應類中的屬性名,不能使用>、<等條件。
當使用filter的時候條件之間是使用==,filter_by使用的是=
filter不支持組合查詢,只能連續調用filter變相實現。filter_by的參數是**kwargs,直接支持組合查詢。框架

1
2
3
4
filters = {'id':1002, 'name':'Bob'}
b = session.query(Student).filter_by(**filters)
for i in b:
    print(i.id, i.name, i.age, i.address)

 

輸出結果

1
1002 Bob 69 beijing

 

  • all()
    返回一個列表,能夠經過遍歷列表獲取每一個對象。
    1
    2
    3
    4
    a = session.query(Student).filter(Student.id > 1001).all()
    print(a)
    for x in a:
        print(x.id, x.name, x.age, x.address)

輸出結果

1
2
3
[<db.orm2.Student object at 0x00000197ECC759E8>, <db.orm2.Student object at 0x00000197ECC75A58>]
1002 Bob 69 beijing
1003 Cerry 14 jiangsu

 

  • one()
    返回且僅返回一個查詢結果。當結果數量不足或者多於一個時會報錯。
    1
    2
    3
    a = session.query(Student).filter(Student.id == 1001).one()
    print(a)
    print(a.id, a.name, a.age, a.address)

輸出結果

1
2
<db.orm2.Student object at 0x000001B7C57E7908>
1001 Alice 25 anhui

 

  • first()
    返回至多一個結果,並且以單項形式,而不是隻有一個元素的tuple形式返回。
    1
    2
    3
    a = session.query(Student).filter(Student.id > 1001).first()
    print(a)
    print(a.id, a.name, a.age, a.address)

輸出結果

1
2
<db.orm2.Student object at 0x000001C63E536B00>
1002 Bob 69 beijing

 

說明

  1. MetaData類
    主要用於保存表結構,鏈接字符串等數據,是一個多表共享的對象。
    metadata = MetaData(engine)綁定一個數據源的metadata。
    metadata.create_all(engine) 建立表,該操做會先判斷表是否存在,若存在則不建立。
  2. Table類
    構造函數爲Table.__init__(self, name, metadata,*args, **kwargs)
    name 表名
    metadata 共享的元數據
    args中Column是列定義
    下面是可變參數`*
    kwargs`定義
    schema 此表的結構名稱,默認None
    autoload 自動從現有表中讀入表結構,默認False
    autoload_with 從其餘engine讀取結構,默認None
    include_columns 若是autoload設置爲True,則此項數組中的列明將被引用,沒有寫的列明將被忽略,None表示全部都列明都引用,默認None
    mustexist 若是爲True,表示這個表必須在其餘的python應用中定義,必須是metadata的一部分,默認False
    useexisting 若是爲True,表示這個表必須被其餘應用定義過,將忽略結構定義,默認False
    owner 表全部者,用於Orcal,默認None
    quote 設置爲True,若是代表是SQL關鍵字,將強制轉義,默認False
    quote_schema 設置爲True,若是列明是SQL關鍵字,將強制轉義,默認False
    mysql_engine mysql專用,能夠設置’InnoDB’或’MyISAM’
  3. Column類
    構造函數爲Column.__init__(self, name, type_, *args, **kwargs)
    name 列名
    type_ 類型,更多類型sqlalchemy.types
    下面是*args參數定義
    Constraint(約束)
    ForeignKey(外鍵)
    ColumnDefault(默認)
    Sequenceobjects(序列)定義
    key 列名的別名,默認None
    下面是**kwargs參數定義
    primary_key 若是爲True,則是主鍵
    nullable 是否可爲Null,默認是True
    default 默認值,默認是None
    index 是不是索引,默認是True
    unique 是否惟一鍵,默認是False
    onupdate 指定一個更新時候的值,這個操做是定義在SQLAlchemy中,不是在數據庫裏的,當更新一條數據時設置,大部分用於updateTime這類字段
    autoincrement 設置爲整型自動增加,只有沒有默認值,而且是Integer類型,默認是True
    quote 若是列明是關鍵字,則強制轉義,默認False
  4. 建立會話
    Session的主要目的是創建與數據庫的會話,它維護你加載和關聯的全部數據庫對象。它是數據庫查詢(Query)的一個入口。
    SQLAlchemy中,數據庫的查詢操做是經過Query對象來實現的,而Session提供了建立Query對象的接口。Query對象返回的結果是一組同一映射(Identity Map)對象組成的集合。事實上,集合中的一個對象,對應於數據庫表中的一行(即一條記錄)。所謂同一映射,是指每一個對象有一個惟一的ID。若是兩個對象(的引用)ID相同,則認爲它們對應的是相同的對象。
    要完成數據庫查詢,就須要創建與數據庫的鏈接。這就須要用到Engine對象。一個Engine多是關聯一個Session對象,也可能關聯一個數據庫表。
    固然Session最重要的功能仍是實現原子操做。
    ORM經過session與數據庫創建鏈接進行通訊,以下所示
    1
    2
    3
    4
    from sqlalchemy.orm import sessionmaker
    
    DBSession = sessionmaker(bind=engine)
    session = DBSession()

經過sessionmake方法建立一個Session工廠,而後在調用工廠的方法來實例化一個Session對象。

要了解更多關於SQLAlchemy內容能夠點擊SQLAlchemy Documentation查看官方介紹。

分享

相關文章
相關標籤/搜索