概述
SQLAlchemy是Python編程語言下的一款ORM框架,該框架建立在數據庫API之上,使用關係對象映射進行數據庫操作,簡言之便是:將對象轉換成SQL,然後使用數據API執行SQL並獲取執行結果。
ORM技術
數據庫表是一個二維表,包含多行多列。把一個表的內容用Python的數據結構表示出來的話,可以用一個list表示多行,list的每一個元素是tuple,表示一行記錄。比如,包含id和name的user表:
[
('1', 'Michael'),
('2', 'Bob'),
('3', 'Adam')
]
Python的DB-API返回的數據結構就是像上面這樣表示的。
但是用tuple表示一行很難看出表的結構。如果把一個tuple用class實例來表示,就可以更容易地看出表的結構來:
class User(object):
def __init__(self, id, name):
self.id = id
self.name = name
[
User('1', 'Michael'),
User('2', 'Bob'),
User('3', 'Adam')
]
上述就是ORM技術:Object-Relational Mapping,把關係數據庫的表結構映射到對象上。
SQLAlchemy
SQLAlchemy-初始化連接
SQLAlchemy本身無法操作數據庫,其必須依賴pymsql等第三方插件,Dialect用於和數據API進行交流,根據配置文件的不同調用不同的數據庫API,從而實現對數據庫的操作。
# pymysql
DB_CONNECT_STRING = 'mysql+pymysql://root:[email protected]:3306/db_stable'
# MySQL-Python
DB_CONNECT_STRING = 'mysql+mysqldb://root:[email protected]:3306/db_stable'
# MySQL-Connector
DB_CONNECT_STRING = 'mysql+mysqlconnector://root:[email protected]:3306/db_stable'
create_engine()返回一個Engine的實例,並且它表示通過數據庫語法處理細節的核心接口,在這種情況下,數據庫語法將會被解釋成python的類方法。
echo參數爲True時,會顯示每條執行的SQL語句,可以關閉。
from sqlalchemy import create_engine
# 初始化數據庫連接
DB_CONNECT_STRING = 'mysql+pymysql://root:[email protected]:3306/db_stable'
Engine = create_engine(DB_CONNECT_STRING, echo=True, pool_recycle=3600)
SQLAlchemy-創建表
__tablename__ 屬性:數據庫中該表的名稱
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine
# 創建對象的基類,declarative_base() 創建了一個 Base類,這個類的子類可以自動與一個表關聯。
Base = declarative_base()
# 創建單表
class Params(Base):
__tablename__ = "t_params"
__table_arge__ = {"extend_existing": True, "useexisting": True}
id = Column(Integer, primary_key=True, autoincrement=True)
package = Column(CHAR(255), nullable=False)
project = Column(CHAR(255), nullable=False)
platform = Column(CHAR(255), nullable=False)
prefix = Column(CHAR(255))
activity = Column(CHAR(255))
# 一對多,外鍵ForeignKey
class Devices(Base):
__tablename__ = "t_devices"
__table_arge__ = {"extend_existing": True, "useexisting": True}
id = Column(Integer, primary_key=True, autoincrement=True)
sn = Column(CHAR(255), nullable=False)
platform = Column(CHAR(50), nullable=False)
idfa = Column(CHAR(255))
uuid = Column(CHAR(255))
unionid = Column(CHAR(255))
product = Column(CHAR(255))
os_version = Column(CHAR(255))
class Jobs(Base):
__tablename__ = "t_jobs"
__table_arge__ = {"extend_existing": True, "useexisting": True}
id = Column(Integer, autoincrement=True, primary_key=True)
device_id = Column(Integer, ForeignKey("t_devices.id"))
user_name = Column(CHAR(255))
business = Column(CHAR(255))
version = Column(CHAR(50))
job_type = Column(CHAR(50))
submit_time = Column(DATETIME)
end_time = Column(DATETIME)
job_status = Column(Integer)
config_name = Column(CHAR(255))
# 多對多
class ServerToGroup(Base):
__tablename__ = 'servertogroup'
nid = Column(Integer, primary_key=True, autoincrement=True)
server_id = Column(Integer, ForeignKey('server.id'))
group_id = Column(Integer, ForeignKey('group.id'))
class Group(Base):
__tablename__ = 'group'
id = Column(Integer, primary_key=True)
name = Column(String(64), unique=True, nullable=False)
class Server(Base):
__tablename__ = 'server'
id = Column(Integer, primary_key=True, autoincrement=True)
hostname = Column(String(64), unique=True, nullable=False)
port = Column(Integer, default=22)
多對多關係:需要轉換成1對多關係,需要一張中間表來轉換,這張中間表裏面需要存放學生表裏面的主鍵和課程表裏面的主鍵,此時學生與中間表示1對多關係,課程與中間表是1對多關係,學生與課程是多對多關係。
SQLAlchemy-創建會話(操作表)
sessionmaker() 會生成一個數據庫會話類。這個類的實例可以當成一個數據庫連接,它同時還記錄了一些查詢的數據,並決定什麼時候執行 SQL 語句。
from sqlalchemy.orm import sessionmaker
# 創建Session對象(mysql操作對象)
Session = sessionmaker(bind=Engine, autoflush=True, expire_on_commit=True)
SQLAlchemy-增、刪、改、查
新增:
@auto_close
def insert_job(body, session=None):
item = Jobs(**body)
session.add(item)
session.flush()
刪除:
@auto_close
def delete_job(data, jobId, session=None):
session.query(Jobs).filter(Jobs.id == jobId).delete
更新:
@auto_close
def update_job(data, jobId, session=None):
session.query(Jobs).filter(Jobs.id == jobId).update(data)
查詢
@auto_close
def get_jobId(sub_time, session=None):
item = session.query(Jobs).filter(Jobs.submit_time == sub_time).first()
jobId = item.id
return jobId
注意:
1.通過Session的query()方法創建一個查詢對象。這個函數的參數數量是可變的,參數可以是任何類或者是類的描述的集合。
2.查詢出來的數據sqlalchemy直接給映射成一個對象(或者是每個元素爲這種對象的列表),對象和創建表時候的class是一致的,可以直接通過對象的屬性直接調用。如:item.id
3.first():返回查詢的第一個結果,如果沒有結果,則返回None
all():以列表形式返回查詢的所有結果
count():返回查詢結果的數量
SQLAlchemy-查詢
查詢過濾器
使用舉例:
filter():過濾表的條件
filter: 可以像寫 sql 的 where 條件那樣寫 > < 等條件,但引用列名時,需要通過"類名.屬性名"的方式。
filter_by: 可以使用 python 的正常參數傳遞方法傳遞條件,指定列名時,不需要額外指定類名。參數名對應類中的屬性名,但似乎不能使用 > < 等條件。
當使用filter的時候條件之間是使用“==",fitler_by使用的是"="。
user1 = session.query(User).filter_by(id=1).first()
user1 = session.query(User).filter(User.id==1).first()
# 條件:== 、!=、like、in、非、>、between
ret = session.query(Users).filter(Users.name =='alex').all()
ret = session.query(Users).filter(Users.name !='alex').all()
ret = session.query(Users).filter(Users.name.like("%alex%")).all()
ret = session.query(Users).filter(Users.id.in_([1,3,4])).all()
ret = session.query(Users).filter(~Users.id.in_([1,3,4])).all() # not in ~爲通配符非
ret = session.query(Users).filter(~Users.name.like('e%')).all()
ret = session.query(Users).filter(Users.id > 1, Users.name == 'eric').all()
ret = session.query(Users).filter(Users.id.between(1, 3), Users.name == 'eric').all()
# AND 以下兩個功能一致
ret = session.query(Users).filter(and_(Users.name == 'fengxiaoqing', Users.id ==10001)).all()
ret = session.query(Users).filter(Users.name == 'fengxiaoqing').filter(Users.address == 'chengde').all()
# OR
ret = session.query(Users).filter(or_(Users.name == 'fengxiaoqing', Users.age ==18)).all()
ret = session.query(Users).filter(
or_(
Users.id < 2,
and_(Users.name == 'eric', Users.id > 3),
Users.extra != ""
)).all()
其餘函數:
# order_by:排序 limit:指定行數
item = session.query(Jobs).order_by(Jobs.id).limit(4)
# desc:倒序顯示 asc:升序
item = session.query(Jobs).order_by(Jobs.id.desc(),Jobs.device_id.asc())
# group_by
ret = session.query(Users).group_by(Users.extra).all()
# func
ret = session.query(
func.max(Users.id),
func.sum(Users.id),
func.min(Users.id)).group_by(Users.name).all()
ret = session.query(
func.max(Users.id),
func.sum(Users.id),
func.min(Users.id)).group_by(Users.name).having(func.min(Users.id) >2).all()
連接查詢join
ret = session.query(Users, Favor).filter(Users.id == Favor.nid).all()
ret = session.query(Person).join(Favor).all()
ret = session.query(Person).join(Favor, isouter=True).all()
子查詢
ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name='eric'))).all()
聯合查詢union
q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union(q2).all()
q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union_all(q2).all()
參考
https://www.cnblogs.com/ccorz/p/5711955.html
https://blog.csdn.net/wuqing942274053/article/details/72571650
mysql查詢操作: