1. SQLalchemy
sqlalchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
2. 创建连接
from sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Indexfrom sqlalchemy.orm import sessionmaker, relationshipfrom sqlalchemy import create_engine# 创建对象的基类Base = declarative_base()# 初始化数据库连接engine = create_engine(#'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'"mysql+pymysql://root:123456@localhost:3306/pyorm",# 对数据库进行编码设置,能对数据库进行中文读写charset="utf8",# pool_size用于设置连接数,默认设置5个pool_size=5,# erflow默认连接数为10。当超出最大连接数后,如果超出的连接数在max_overflow设置的访问内,超出部分可以继续连接访问,max_overflow=4,# pool_recycle: 连接重置周期,默认为-1,推荐设置为7200,即如果连接已空闲7200秒,就自动重新获取,防止connection被关闭pool_recycle=7200,# pool_timeout:连接超时时间,默认为30秒,超过时间的连接会连接失败pool_timeout=30)# 创建DBSession类型DBSession = sessionmaker(bind=engine)
- echo=False — 如果为真,引擎将记录所有语句以及
repr()其参数列表的默认日志处理程序。 - enable_from_linting — 默认为True。如果发现给定的SELECT语句与将导致笛卡尔积的元素取消链接,则将发出警告。
- encoding — 默认为
utf-8 - future — 使用2.0样式
- hide_parameters — 布尔值,当设置为True时,SQL语句参数将不会显示在信息日志中,也不会格式化为 StatementError 对象。
- listeners — 一个或多个列表
PoolListener将接收连接池事件的对象。 - logging_name — 字符串标识符,默认为对象id的十六进制字符串。
- max_identifier_length — 整数;重写方言确定的最大标识符长度。
- max_overflow=10 — 允许在连接池中“溢出”的连接数,即可以在池大小设置(默认为5)之上或之外打开的连接数。
- pool_size=5 — 在连接池中保持打开的连接数
- plugins — 要加载的插件名称的字符串列表。
3. 定义映射对象
必须先初始化连接
tablename 代表表名
Column : 代表数据表中的一列,内部定义了数据类型
primary_key:主键
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index# 定义User对象:class User(Base):# 表的名字:__tablename__ = 'user'# 表的结构:id = Column(String(20), primary_key=True)name = Column(String(20))
primary_key=True主键索引
autoincrement=True自增字段
index=True给当前字段创建普通索引
unique=True给当前字段创建唯一索引
UniqueConstraint(‘字段’,’字段’,name=’索引名称’)创建唯一组合索引
Index(‘索引名称’,’字段’,’字段’)创建普通组合索引
default=’abc’设置字段默认值,不怎么可靠
ForeignKey(“连接表名称.连接表主键字段”)设置外键链表
nullable=False类容不能为空
整数型:TINYINT,SMALLINT,INT,BIGINT
- Boolean()对应TINYINT
- Integer()对应INT
- SMALLINT()对应SMALLINT
- BIGINT()对应BIGINT
浮点型:FLOAT,DOUBLE,DECIMAL(M,D)
- DECIMAL()对应DECIMAL
- Float()对应FLOAT
- REAL()对应DOUBLE
字符型:CHAR,VARCHAR
- String(40)对应VARCHAR
- CHAR()对应CHAR
日期型:DATETIME,DATE,TIMESTAMP
- DATETIME()对应DATETIME
- DATE()对应DATE
- TIMESTAMP()对应TIMESTAMP
备注型:TINYTEXT,TEXT,
- Text()对应TEXT
- UnicodeText(10)对应TINYTEXT
4. 一对多映射类
通过外键绑定主键
class User(Base):__tablename__ = 'user'id = Column(String(20), primary_key=True)name = Column(String(20))# 一对多:books = relationship('Book')class Book(Base):__tablename__ = 'book'id = Column(String(20), primary_key=True)name = Column(String(20))# “多”的一方的book表是通过外键关联到user表的:user_id = Column(String(20), ForeignKey('user.id'))
5. 多对多
class Server(Base):__tablename__ = "server"id = Column(Integer, primary_key=True, autoincrement=True)hostname = Column(String(8))class Group(Base):__tablename__ = "group"id = Column(Integer, primary_key=True, autoincrement=True)name = Column(String(16), unique=True)class ServertoGroup(Base):__tablename__ = "servertogroup"id = Column(Integer, primary_key=True, autoincrement=True)server_id = Column(Integer, ForeignKey('server.id'))group_id = Column(Integer, ForeignKey('group.id'))
6. 创建表
必须创建映射类并指定表名 才会创建 如表存在不进行操作 如无则创建
class Lagoujob(Base):# 指定表名__tablename__='lagoujob'id=Column(Integer,primary_key=True)area=Column(String(50))community=Column(String(50))village=Column(String(50))engine = create_engine("mysql+pymysql://root:123456@localhost:3306/pyorm", max_overflow=4)Base.metadata.create_all(engine)
7. 增删改查
7.1. 增
# 创建session对象:session = DBSession()# 创建新User对象:new_user = User(id='5', name='Bob')# 添加到session:session.add(new_user)# 提交即保存到数据库:session.commit()# 关闭session:session.close()
7.2. 删
user = session.query(User).filter(User.id=='5').first()session.delete(user)session.commit()
7.3. 改
emp = session.query(Employee).filter_by(EMP_ID='9002').first()emp.AGE = '21'session.commit()#写法二session.query(table1).filter(table1.id > 8).update({table1.age: 11})
7.4. 查
- query.filter() 过滤
- query.filter_by() 根据关键字过滤
- query.all() 返回列表
- query.first() 返回第一个元素
- query.one() 有且只有一个元素时才正确返回
- query.one_or_none(),类似one,但如果没有找到结果,则不会引发错误
- query.scalar(),调用one方法,并在成功时返回行的第一列
- query.count() 计数
- query.order_by() 排序
# 创建Session:session = DBSession()# 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行:user = session.query(User).filter(User.id=='5').one()# Query 对象提供了 filter() 方法和 filter_by() 方法用于数据筛选。filter_by() 适用于简单的基于关键字参数的筛选。 filter() 适用于复杂条件的表达。user = session.query(User).filter_by(User.id=='5').first()# 多条件查询 条件之间用逗号隔开get_data = session.query(table1).filter(table1.id > 1, table1.age > 5).all()# 查询所有all_user = session.query(User).all()# 只获取指定字段 返回为由元组组成的listall = session.query(user.id, user.name).all()#输出查询结果 默认为list[user_Object]print(all_user)# 关闭Session:session.close()
query.join() 连接查询
join分为left join(左外连接)和right join(右外连接)以及内连接(等值连接)。- 在
sqlalchemy中,使用join来完成内连接。在写join的时候,如果不写join的条件,那么默认将使用外键来作为条件连接。 - 查询出来的字段,跟
join后面的东西无关,而是取决于query方法中传了什么参数。(模型名=全表;模型名.属性=表名.字段)。 - 在
sqlalchemy中,使用outer join来完成外连接(默认是左外连接)。session.query(BvVideo.ctime,UpAuthor.name).join(UpAuthor,BvVideo.mid == UpAuthor.up_mid).all()
query(column.label()) 别名
session.query(User.name.label('name_label')).all()
- aliased()为查询对象设置别名
user_alias = aliased(User, name='user_alias')
#== <= >=def test_filter_le(self):emps = session.query(Employee).filter(Employee.EMP_ID <= '1009').all()print(to_formatted_table(emps))#!=def test_filter_ne(self):emps = session.query(Employee).filter(Employee.EMP_ID != '1001').all()print(to_formatted_table(emps))#likedef test_filter_like(self):emps = session.query(Employee).filter(Employee.EMP_ID.like('%9')).all() #不区分大小写print(to_formatted_table(emps))#indef test_filter_in(self):emps = session.query(Employee).filter(Employee.EDUCATION.in_(['Bachelor', 'Master'])).all()print(to_formatted_table(emps))#not indef test_filter_notin(self):emps = session.query(Employee).filter(~Employee.EDUCATION.in_(['Bachelor', 'Master'])).all()print(to_formatted_table(emps))#is nulldef test_filter_isnull(self):emps = session.query(Employee).filter(Employee.MARITAL_STAT == None).all()print(to_formatted_table(emps))#is not nulldef test_filter_isnotnull(self):emps = session.query(Employee).filter(Employee.MARITAL_STAT != None).all()print(to_formatted_table(emps))#ansdef test_filter_and(self):emps = session.query(Employee).filter(Employee.GENDER=='Female', Employee.EDUCATION=='Bachelor').all()print(to_formatted_table(emps))#anddef test_filter_and2(self):emps = session.query(Employee).filter(and_(Employee.GENDER=='Female', Employee.EDUCATION=='Bachelor')).all()print(to_formatted_table(emps))#ordef test_filter_or(self):emps = session.query(Employee).filter(or_(Employee.MARITAL_STAT=='Single', Employee.NR_OF_CHILDREN==0)).all()print(to_formatted_table(emps))
7.6. 书写sql语句
from sqlalchemy import textsession.query(User).filter(text("id<:value and name=:name")).params(value=224, name='fred').order_by(User.id).one()
8. 回滚
在 commit() 之前,对实例对象的属性所做的更改,可以进行回滚,回到更改之前。
本质上只是把某一条数据(也就是映射类的实例)从内存中删除而已,并没有对数据库有任何操作。
session.rollback()
