sqlalchemy从入门到熟悉(一)
简介
SQLAlchemy SQL工具包和对象关系映射器是一套用于处理数据库和Python的综合工具。它有几个不同的功能领域,可以单独使用或组合使用。SQLAlchemy的两个最重要的面向前端的部分是对象关系映射器(ORM)以及Core。核心包含SQLAlchemy 的SQL以及数据库集成和描述服务的广度,其中最突出的部分是SQL表达式语言。
-
SQL表达式语言是一个完全独立于ORM包的工具包,它提供了一个构造由可组合对象表示的SQL表达式的系统,然后可以针对特定事务范围内的目标数据库“执行”这些SQL表达式,并返回结果集。插入、更新和删除是通过传递表示这些语句的SQL表达式对象以及表示要与每个语句一起使用的参数的字典来实现的。
-
ORM构建在Core之上,以提供使用映射到数据库模式的域对象模型的方法。在使用ORM时,SQL语句的构造方式与使用Core时基本相同,但是DML的任务是使用工作单元,它将针对可变对象的状态更改转换为INSERT、UPDATE和DELETE构造,然后根据这些对象调用这些构造。特定于ORM的自动化和以对象为中心的查询功能也增强了SELECT语句。
-
使用Core和SQL表达式语言提供了一个以模式为中心的数据库视图,以及一个面向不变性的编程范例,而ORM则在此基础上构建了一个以域为中心的数据库视图,具有更明显的面向对象和依赖于可变性的编程范例。由于关系数据库本身是可变服务,不同之处在于Core/SQL表达式语言是面向命令的,而ORM是面向状态的。
-
支持的安装方法
(1)使用PIP安装
pip install SQLAlchemy
# 安装最新的预缓解版本,使用--pre
pip install --pre SQLAlchemy
(2)SQLAlchemy安装是通过标准Python方法进行的,这些方法基于setuptools,可以通过引用setup.py
直接使用。
python setup.py install
(3)检查已安装的SQLAlchemy版本
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.4.41'
建立连接
- 任何SQLAlchemy应用程序的开始都是一个名为
Engine
。此对象充当连接到特定数据库的中心源,提供工厂和连接池。引擎通常是一个职位特定数据库服务器创建一次的全局对象,并使用一个URL字符串进行配置。
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:root@localhost:3306/test')
处理事务和DBAPI
- 获取连接
from sqlalchemy import create_engine, text
engine = create_engine('mysql+pymysql://root:root@localhost:3306/test')# with语句是python的上下文管理器
with engine.connect() as conn:result = conn.execute(text("select 'hello world'"))print(result.all())
结果:
[(‘hello world’,)]
- 提交更改
#DBAPI是非自动提交的,可以使用`commit()`方法提交
with engine.connect() as conn:conn.execute(text("create table demo(x int, y int)"))conn.execute(text("insert into demo(x, y) values(:x, :y)"), [{"x": 1, "y": 1}, {"x": 2, "y": 4}])conn.commit()
- 获取返回结果
with engine.connect() as conn:# REsul有很多用于获取和转换行的方法,类似于python的命名元组result = conn.execute(text("SELECT x, y FROM demo"))# 整数索引for row in result:print(f"x: {row.x} y: {row.y}")# 元组赋值 for x, y in result:print(x)# 属性名称for row in result:y = row.y# 映射访问for dict_row in result.mappings():x = dict_row['x']
- 将参数与语句绑定
# TextClause.bindparams()返回SQL构造的新副本,并添加了其他状态
stmt = text("select x, y from demo where y > :y order by x, y").bindparams(y=6)
- 使用ORM会话执行
from sqlalchemy.orm import Session
stmt = text("SELECT x, y FROM some_table WHERE y > :y ORDER BY x, y").bindparams(y=6)
with Session(engine) as session:result = session.execute(stmt)for row in result:print(f"x: {row.x} y: {row.y}")
使用数据库元数据
-
SQLAlchemy中数据库元数据最常见的基本对象是
MetaData
,Table
和Column
。 -
使用表对象设置元数据
from sqlalchemy import MetaData
# MetaData对象是放置表的地方,一旦拥有了MetaData对象,可以声明一些Table物体
metadata_obj = MetaData()
from sqlalchemy import Table, Column, Integer, String
# Table表示数据库表并将其自身分配给MetaData收集
user = Table("user_account",metadata_obj,# Column表示数据库中的列,收藏Column对象的父对象Table通常位于Table.cColumn('id', Integer, primary_key=True),Column('name', String(30)),Column('fullname', String)
)user.c.name
user.c.keys()
- 使用ORM定义表元数据
(1)设置注册表
#使用ORM时,MetaData集合仍然存在,但是它本身包含`registry`中
from sqlalchemy.orm import registry
# registry在构造时,自动包含MetaData对象,该对象将存储Table
mapper_registry = registry()
mapper_registry.metadata
# 通过应用于映射类的指令间接声明Table对象
Base = mapper_registry.generate_base()
# 创建registry声明性基类可以使用declarative_base()功能
#from sqlalchemy.orm import declarative_base
#Base = declarative_base()
(2)声明映射类
# Base是一个python类,作为声明的OR吗映射类的基类
from sqlalchemy.orm import relationship
from sqlalchemy import Integer, String, ForeignKey, Columnclass User(Base):__tablename__ = 'user_account'id = Column(Integer, primary_key=True)name = Column(String(30))fullname = Column(String)addresses = relationship("Address", back_populates="user")def __repr__(self):return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"class Address(Base):__tablename__ = 'address'id = Column(Integer, primary_key=True)email_address = Column(String, nullable=False)user_id = Column(Integer, ForeignKey('user_account.id'))user = relationship("User", back_populates="addresses")def __repr__(self):return f"Address(id={self.id!r}, email_address={self.email_address!r})"
插入带核心的行
使用Core时,SQL INSERT语句是使用
insert()
函数表示SQL中的INSERT语句,将数据添加到表中。
(1)INSERT() SQL表达式构造
from sqlalchemy import insert
from sqlalchemy import create_engine
# stmt变量是Insert,大多数SQL表达式都可以串行化
stmt = insert(user_table).values(name='spongebob', fullname="Spongebob Squarepants")
print(stmt)
# 字符串形式是通过生活曾Compiled对象的形式
compiled = stmt.compile()
compiled.params
engine = create_engine('mysql+pymysql://root:root@localhost:3306/test')
with engine.connect() as conn:res = conn.execute(stmt)conn.commit()
(2)INSERT通常自动生成VALUES子句
with engine.connect() as conn:result = conn.execute(insert(user_table),[{"name": "sandy", "fullname": "Sandy Cheeks"}, {"name": "patrick", "fullname": "Patrick Star"}])conn.commit()
(3)插入从SELECT
select_stmt = select(user_table.c.id, user_table.c.name + "@aol.com")
insert_stmt = insert(address_table).from_select(["user_id", "email_address"], select_stmt)
(4)INSERT…RETURNING
insert_stmt = insert(address_table).returning(address_table.c.id, address_table.c.email_address)
使用核心或ORM选择行
select()
函数会生成Select
用于所有SELECT查询的构造,传递给这样的方法Connection.execute()
或Session.execute()
,在当前事务中发出SELECT语句,结果行通过Result
对象返回。
(1)SELECT()表达式构造
from sqlalchemy import select
stmt = select(user_table).where(user_table.c.name == 'spongebob')
print(stmt)
with Session(engine) as session:for row in session.execute(stmt):print(row)
(2)设置COLUMNS和FROM子句
# 将所有字段名作为结果集返回
print(select(user_table))
(3)查询实例
from sqlalchemy import Column, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base# 创建对象的基类,需要在数据库中创建表
Base = declarative_base()
class Person(Base):__tablename__ = 'person'id = Column(String(20), primary_key=True)name = Column(String(20))# 初始化数据库连接
engine = create_engine('mysql+pymysql://root:root@localhost:3306/test')
# 创建DBSession类型
DBSession = sessionmaker(bind=engine)
# 创建session对象
session = DBSession()
new_person = Person(id='5', name='Bob')
session.add(new_person)
session.commit()
person = session.query(Person).filter(Person.id=='5').one()
print('type:', type(person))
print('name:', person.name)
session.close()