Python操做MySql——使用SQLAlchemy ORM操做數據庫

1 基礎知識介紹

1.1 ORM框架介紹

ORM(Object Ralational Mapping,對象關係映射),用來把對象模型表示的對象映射到基於S Q L 的關係模型數據庫結構中去。咱們在具體的操做實體對象的時候,就不須要再去和複雜的 SQ L 語句打交道,只需簡單的操做實體對象的屬性和方法。
python

常見的ORM框架mysql

SQLAlchemy:SQLAlchemy 採用了數據映射模式,其工做單元主要使得有必要限制全部的數據庫操做代碼到一個特定的數據庫session,在該session中控制每一個對象的生命週期 。web

SQLObject:是一種流行的對象關係管理器,用於爲數據庫提供對象接口,其中表爲類,行爲實例,列爲屬性。SQLObject包含一個基於Python對象的查詢語言,使SQL更抽象,併爲應用程序提供了大量的數據庫獨立性。sql

Storm :是一個介於 單個或多個數據庫與Python之間 映射對象的 Python ORM 。爲了支持動態存儲和取回對象信息,它容許開發者構建跨數據表的複雜查詢。Stom中 table class 不須要是框架特定基類 的子類 。每一個table class是 的sqlobject.SQLObject 的子類。
數據庫

Django's ORM :由於Django的ORM 是緊嵌到web框架的,因此就算能夠也不推薦,在一個獨立的非Django的Python項目中使用它的ORM。Django,一個最流行的Python web框架, 有它獨有的 ORM。 相比 SQLAlchemy, Django 的 ORM 更吻合於直接操做SQL對象,操做暴露了簡單直接映射數據表和Python類的SQL對象 。bash

1.2 SQLAlchemy介紹

sqlalchemy是Python ORM的開源框架,使用它能夠快速方便的構建數據庫模型
服務器

SQLAlchemy框架session



  • Engine: 框架的引擎
  • Connection Pooling : 數據庫鏈接池
  • Dialect : 選擇鏈接數據庫的DB API類型
  • Schema / Type : 架構和類型
  • SQL Expression Language: SQL表達式語言

SQLALchemy自己沒法操做數據庫,須要依賴pymysql第三方模塊,Dialect用於和數據API進行交流,根據配置文件的不一樣調用不一樣的數據庫API,從而實現對數據庫的操做架構

使用pymysql鏈接數據庫格式:app

mysql + pymysql: / / <username>:<password>@<host> / <dbname>[?<options>]

2 使用SQLAlchemy

2.1安裝SQLAlchemy與檢查是否安裝成功

#安裝
pip install SQLAlchemy
#檢查是否安裝成功
C:\Users\lsl\Desktop>python
Python 3.7.0rc1 (v3.7.0rc1:dfad352267, Jun 12 2018, 07:05:25) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.3.18'複製代碼

2.2使用SQLAlchemy對數據庫的表進行操做

2.2.1建立鏈接對象也就是爲了鏈接到本地的數據庫

create_engine中的字段的意義介紹:

engine = create_engine('dialect+driver://username:password@host:port/database')

dialect -- 數據庫類型     

driver -- 數據庫驅動選擇(個人數據庫驅動選擇是pymysql,默認會調用MySQLdb,若是運行的時候提示ImportError: No module named 'MySQLdb'/ImportError: No module named 'pymysql',則意味着沒有安裝你想使用的數據驅動,安裝命令:pip install pymysql)

username -- 數據庫用戶名

password -- 用戶密碼

host 服務器地址

port 端口

database 數據庫

建立鏈接:

from sqlalchemy import create_engine
# 鏈接本地test數據庫
engine = create_engine('mysql+pymysql://root:root@localhost:3306/testdab',#數據庫類型是mysql,採用pymysql數據庫驅動來鏈接,用戶名是root,密碼也是root,鏈接本地數據庫testdab(鏈接的數據庫要是已存在的,就是你本地已有的數據庫)
                       encoding='utf-8',  # 編碼格式
                       echo=True,  # 是否開啓sql執行語句的日誌輸出
                       pool_recycle=-1,  # 多久以後對線程池中的線程進行一次鏈接的回收(重置) (默認爲-1),其實session並不會被close
                       poolclass=NullPool  # 無限制鏈接數
                       )複製代碼

2.2.2 簡單查詢——使用SQL語句

result = engine.execute("select * from students")//在execute()裏的參數是查詢的sql語句
print(result.fetchall()) //打印出查詢的結果複製代碼

2.2.3 建立映射

建立映射後咱們就能夠減小sql語句對數據庫的操做,而是經過操做咱們創建的與數據庫中的數據表的class來對數據庫中的數據進行操做。

建立一個py文件來作數據表的映射text2.py

#引入要使用的declarative_base
from sqlalchemy.ext.declarative import declarative_base
#在要映射的數據表students中有id,name兩個字段,因此要引入Integer對應id,String對應name
from sqlalchemy import Column, Integer, String
#聲名Base
Base = declarative_base()
#User類就是對應於 __tablename__ 指向的表,也就是數據表students的映射
class User(Base):
#students表是我本地數據庫testdab中已存在的
    __tablename__ = 'students'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64),nullable=False)
    __table_args__ = {
        "mysql_charset": "utf8"
    }複製代碼

在要進行操做以前還要建立一下會話,Session的主要目的是創建與數據庫的會話,它維護你加載和關聯的全部數據庫對象。它是數據庫查詢(Query)的一個入口。在Sqlalchemy中,數據庫的查詢操做是經過Query對象來實現的。而Session提供了建立Query對象的接口。

# 建立會話
session = sessionmaker(engine)
mySession = session()複製代碼

接下來,咱們就能夠經過操做User類來操做數據表students

2.2.4 查詢

查詢students表中全部的數據

result = mySession.query(News).all()
print(result[0])複製代碼

查詢students表中第一條數據

result = mySession.query(User).first()
print(result.name) #打印對象屬性複製代碼

經過id查詢數據(id=2)

result = mySession.query(User).filter_by(id=2).first()
print(result.name)複製代碼

自定義過濾條件

result = mySession.query(User).filter(text("id>:id")).params(id=2).all()複製代碼

根據主鍵查詢

result = mySession.query(User).get(2)複製代碼

其餘查詢操做介紹

  • all() 返回查詢到的全部的結果。這個方法比較危險的地方是,若是數據量大且沒有使用limit子句限制的話,全部的結果都會加載到內存中。它返回的是一個列表,若是查詢不到任何結果,返回的是空列表。
  • first() 返回查詢到的第一個結果,若是沒有查詢到結果,返回None
  • .scalar() 這個方法與.one_or_none()的效果同樣。 若是查詢到不少結果,拋出sqlalchemy.orm.exc.MultipleResultsFound異常。若是隻有一個結果,返回它,沒有結果返回None
  • one() 若是隻能查詢到一個結果,返回它,不然拋出異常。沒有結果時拋sqlalchemy.orm.exc.NoResultFound,有超過一個結果時拋sqlalchemy.orm.exc.MultipleResultsFound
  • one_or_none()比起one()來,區別只是查詢不到任何結果時再也不拋出異常而是返回None
  • get()這是個比較特殊的方法。它用於根據主鍵來返回查詢結果,所以它有個參數就是要查詢的對象的主鍵。若是沒有該主鍵的結果返回None,不然返回這個結果。

2.2.5 增長數據(添加一條數據 name=」小紅「),注意要commit

user = User(name="小紅")
mySession.add(user)
mySession.commit()
複製代碼

2.2.6刪除數據(根據id進行修改)

mySession.query(User).filter(User.id == 1).delete()
mySession.commit()複製代碼

2.2.7修改數據(修改一條數據,把小紅的名字修改爲小白)

mySession.query(User).filter(User.name=="小紅").update({"name":"小白"})
mySession.commit()複製代碼

3 經常使用條件查詢代碼

表名:User

1.條件查詢
session.query(User).filter(User.name=='張三'){
                                               .all()   查詢全部
                                               .one()   查詢單個(若是存在多個會異常)
                                               .first() 查詢符合條件的第一個
                                               .limit(1).one() limit限制查詢,limit(1).one()升級第一個
                                               .count()  查詢符合條件的總個數
                                               }

2.主鍵查詢
session.query(User).get(0)  查詢主鍵ID=0

3.offset(n) 限制前面n個,顯示後面n+1個
#查詢出第三個後面的全部
session.query(User).offset(3).all()

4.slice()切片
#slice(1,3) 與python的slice一致,從0開始 左閉右開,顯示1,2兩個元素
session.query(User).slice(1,,3).all()

5.order_by() 默認升序
session.query(User).order_by(User.id).all()

6.desc() 降序
session.query(User).order_by(desc(User.id)).all()

7.like 模糊匹配,與sql同樣
session.query(User).filter(User.neme.like('%吳')).add()

8.notlike 與7相反


form operator import *

9.in_() 包含
#查詢是否包含唐人、吳新喜這個用戶的信息
session.query(User).filter(User.name.in_(['唐人','吳新喜'])).all()


10.notin_() 不包含

11.is_  兩種表達方式 None
#查詢全部手機號爲null的信息
session.query(User).filter(User.phone==None).all()
session.query(User).filter(User.phone.is_(None)).all()

12. isnot()

13. or_ 條件或者關係
#查詢name==吳新喜或者唐人的用戶信息
session.query(User).filter(or_(User.name=='唐人',User.name=='吳新喜'))

聚合函數

1.count group_by
#查詢全部的密碼而且計算其相同的個數
from sqlalchemy import func
ssession.query(db_user.psw,func.count(db_user.psw)).group_by(db_user.psw).all()

2.having
having字句可讓咱們篩選成組後的各類數據,where字句在聚合前先篩選記錄,也就是說做用在group by和having字句前。
而having子句在聚合後對組記錄進行篩選。真實表中沒有此數據,這些數據是經過一些函數生存。
即先成組在篩選

#查詢全部的密碼而且計算其相同的個數,having條件相同密碼總數大於1的數據
ssession.query(db_user.psw,func.count(db_user.psw)).group_by(db_user.psw).having(func.count(db_user.psw)>1).all()

3.sum
#計算全部id的總和
ssession.query(func.sum(db_user.id)).all()

4.max
#最大的ID
 ssession.query(func.max(db_user.id)).all()

5.min
#最小的id
 ssession.query(func.min(db_user.id)).all()

6.lable 別名
lable別名不能用在having中

7.extract 提取時間元素
from sqlalchemy import extract複製代碼

4 總的代碼

#import
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool

#建立鏈接對象也就是爲了鏈接到本地的數據庫
engine = create_engine('mysql+pymysql://root:root@localhost:3306/testdab',
                       encoding='utf-8',  # 編碼格式
                       echo=True,  # 是否開啓sql執行語句的日誌輸出
                       pool_recycle=-1,  # 多久以後對線程池中的線程進行一次鏈接的回收(重置) (默認爲-1),其實session並不會被close
                       poolclass=NullPool  # 無限制鏈接數
                       )
		
#聲名Base
Base = declarative_base()

# 建立會話
session = sessionmaker(engine)
mySession = session()

		
# 建立類,繼承基類,用基本類型描述數據庫結構
class User(Base):
    __tablename__ = 'students'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64),nullable=False)
    __table_args__ = {
        "mysql_charset": "utf8"
    }
	
#sql語句查詢
result = engine.execute("select * from students")
print(result.fetchall()) 

# 查詢第一條
result = mySession.query(User).first()
print(result.name) #打印對象屬性

# 查詢全部
result = mySession.query(User).all()
print(result[0])

# 查詢id爲2的
result = mySession.query(User).filter_by(id=2).first()
print(result.name)

# 分頁查詢 0,2
result = mySession.query(User).filter(User.id>1).limit(2).offset(0).all()
print(result)

#插入新數據
user = User(name="小紅")
mySession.add(user)
mySession.commit()
result = mySession.query(User).filter_by(name="小紅").first()
print(result.name)


#修改已有數據
mySession.query(User).filter(User.name=="小紅").update({"name":"小白"})
mySession.commit()
result = mySession.query(User).filter_by(name="小白").first()
print(result.name)

#刪除數據
mySession.query(User).filter(User.id == 1).delete()
mySession.commit()
result = mySession.query(User).first()
print(result.name) #打印對象屬性複製代碼
相關文章
相關標籤/搜索