1. SQLalchemy

sqlalchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

2. 创建连接

  1. from sqlalchemy.ext.declarative import declarative_base
  2. from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
  3. from sqlalchemy.orm import sessionmaker, relationship
  4. from sqlalchemy import create_engine
  5. # 创建对象的基类
  6. Base = declarative_base()
  7. # 初始化数据库连接
  8. engine = create_engine(
  9. #'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'
  10. "mysql+pymysql://root:123456@localhost:3306/pyorm",
  11. # 对数据库进行编码设置,能对数据库进行中文读写
  12. charset="utf8",
  13. # pool_size用于设置连接数,默认设置5个
  14. pool_size=5,
  15. # erflow默认连接数为10。当超出最大连接数后,如果超出的连接数在max_overflow设置的访问内,超出部分可以继续连接访问,
  16. max_overflow=4,
  17. # pool_recycle: 连接重置周期,默认为-1,推荐设置为7200,即如果连接已空闲7200秒,就自动重新获取,防止connection被关闭
  18. pool_recycle=7200,
  19. # pool_timeout:连接超时时间,默认为30秒,超过时间的连接会连接失败
  20. pool_timeout=30)
  21. # 创建DBSession类型
  22. 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:主键

  1. from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
  2. # 定义User对象:
  3. class User(Base):
  4. # 表的名字:
  5. __tablename__ = 'user'
  6. # 表的结构:
  7. id = Column(String(20), primary_key=True)
  8. 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

  1. Boolean()对应TINYINT
  2. Integer()对应INT
  3. SMALLINT()对应SMALLINT
  4. BIGINT()对应BIGINT

浮点型:FLOAT,DOUBLE,DECIMAL(M,D)

  1. DECIMAL()对应DECIMAL
  2. Float()对应FLOAT
  3. REAL()对应DOUBLE

字符型:CHAR,VARCHAR

  1. String(40)对应VARCHAR
  2. CHAR()对应CHAR

日期型:DATETIME,DATE,TIMESTAMP

  1. DATETIME()对应DATETIME
  2. DATE()对应DATE
  3. TIMESTAMP()对应TIMESTAMP

备注型:TINYTEXT,TEXT,

  1. Text()对应TEXT
  2. UnicodeText(10)对应TINYTEXT

4. 一对多映射类

通过外键绑定主键

  1. class User(Base):
  2. __tablename__ = 'user'
  3. id = Column(String(20), primary_key=True)
  4. name = Column(String(20))
  5. # 一对多:
  6. books = relationship('Book')
  7. class Book(Base):
  8. __tablename__ = 'book'
  9. id = Column(String(20), primary_key=True)
  10. name = Column(String(20))
  11. # “多”的一方的book表是通过外键关联到user表的:
  12. user_id = Column(String(20), ForeignKey('user.id'))

5. 多对多

  1. class Server(Base):
  2. __tablename__ = "server"
  3. id = Column(Integer, primary_key=True, autoincrement=True)
  4. hostname = Column(String(8))
  5. class Group(Base):
  6. __tablename__ = "group"
  7. id = Column(Integer, primary_key=True, autoincrement=True)
  8. name = Column(String(16), unique=True)
  9. class ServertoGroup(Base):
  10. __tablename__ = "servertogroup"
  11. id = Column(Integer, primary_key=True, autoincrement=True)
  12. server_id = Column(Integer, ForeignKey('server.id'))
  13. group_id = Column(Integer, ForeignKey('group.id'))

6. 创建表

必须创建映射类并指定表名 才会创建 如表存在不进行操作 如无则创建

  1. class Lagoujob(Base):
  2. # 指定表名
  3. __tablename__='lagoujob'
  4. id=Column(Integer,primary_key=True)
  5. area=Column(String(50))
  6. community=Column(String(50))
  7. village=Column(String(50))
  8. engine = create_engine("mysql+pymysql://root:123456@localhost:3306/pyorm", max_overflow=4)
  9. Base.metadata.create_all(engine)

7. 增删改查

7.1. 增

  1. # 创建session对象:
  2. session = DBSession()
  3. # 创建新User对象:
  4. new_user = User(id='5', name='Bob')
  5. # 添加到session:
  6. session.add(new_user)
  7. # 提交即保存到数据库:
  8. session.commit()
  9. # 关闭session:
  10. session.close()

7.2. 删

  1. user = session.query(User).filter(User.id=='5').first()
  2. session.delete(user)
  3. session.commit()

7.3. 改

  1. emp = session.query(Employee).filter_by(EMP_ID='9002').first()
  2. emp.AGE = '21'
  3. session.commit()
  4. #写法二
  5. 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() 排序
  1. # 创建Session:
  2. session = DBSession()
  3. # 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行:
  4. user = session.query(User).filter(User.id=='5').one()
  5. # Query 对象提供了 filter() 方法和 filter_by() 方法用于数据筛选。filter_by() 适用于简单的基于关键字参数的筛选。 filter() 适用于复杂条件的表达。
  6. user = session.query(User).filter_by(User.id=='5').first()
  7. # 多条件查询 条件之间用逗号隔开
  8. get_data = session.query(table1).filter(table1.id > 1, table1.age > 5).all()
  9. # 查询所有
  10. all_user = session.query(User).all()
  11. # 只获取指定字段 返回为由元组组成的list
  12. all = session.query(user.id, user.name).all()
  13. #输出查询结果 默认为list[user_Object]
  14. print(all_user)
  15. # 关闭Session:
  16. session.close()
  • query.join() 连接查询

    • join分为left join(左外连接)和right join(右外连接)以及内连接(等值连接)。
    • sqlalchemy中,使用join来完成内连接。在写join的时候,如果不写join的条件,那么默认将使用外键来作为条件连接。
    • 查询出来的字段,跟join后面的东西无关,而是取决于query方法中传了什么参数。(模型名=全表;模型名.属性=表名.字段)。
    • sqlalchemy中,使用outer join来完成外连接(默认是左外连接)。
      1. session.query(BvVideo.ctime,UpAuthor.name).join(UpAuthor,BvVideo.mid == UpAuthor.up_mid).all()
  • query(column.label()) 别名

    1. session.query(User.name.label('name_label')).all()
  • aliased()为查询对象设置别名
    1. user_alias = aliased(User, name='user_alias')
  • 7.5. 一些常用条件的query查询

  1. #== <= >=
  2. def test_filter_le(self):
  3. emps = session.query(Employee).filter(Employee.EMP_ID <= '1009').all()
  4. print(to_formatted_table(emps))
  5. #!=
  6. def test_filter_ne(self):
  7. emps = session.query(Employee).filter(Employee.EMP_ID != '1001').all()
  8. print(to_formatted_table(emps))
  9. #like
  10. def test_filter_like(self):
  11. emps = session.query(Employee).filter(Employee.EMP_ID.like('%9')).all() #不区分大小写
  12. print(to_formatted_table(emps))
  13. #in
  14. def test_filter_in(self):
  15. emps = session.query(Employee).filter(Employee.EDUCATION.in_(['Bachelor', 'Master'])).all()
  16. print(to_formatted_table(emps))
  17. #not in
  18. def test_filter_notin(self):
  19. emps = session.query(Employee).filter(~Employee.EDUCATION.in_(['Bachelor', 'Master'])).all()
  20. print(to_formatted_table(emps))
  21. #is null
  22. def test_filter_isnull(self):
  23. emps = session.query(Employee).filter(Employee.MARITAL_STAT == None).all()
  24. print(to_formatted_table(emps))
  25. #is not null
  26. def test_filter_isnotnull(self):
  27. emps = session.query(Employee).filter(Employee.MARITAL_STAT != None).all()
  28. print(to_formatted_table(emps))
  29. #ans
  30. def test_filter_and(self):
  31. emps = session.query(Employee).filter(Employee.GENDER=='Female', Employee.EDUCATION=='Bachelor').all()
  32. print(to_formatted_table(emps))
  33. #and
  34. def test_filter_and2(self):
  35. emps = session.query(Employee).filter(and_(Employee.GENDER=='Female', Employee.EDUCATION=='Bachelor')).all()
  36. print(to_formatted_table(emps))
  37. #or
  38. def test_filter_or(self):
  39. emps = session.query(Employee).filter(or_(Employee.MARITAL_STAT=='Single', Employee.NR_OF_CHILDREN==0)).all()
  40. print(to_formatted_table(emps))

7.6. 书写sql语句

  1. from sqlalchemy import text
  2. session.query(User).filter(text("id<:value and name=:name")).params(value=224, name='fred').order_by(User.id).one()

8. 回滚

commit() 之前,对实例对象的属性所做的更改,可以进行回滚,回到更改之前。

本质上只是把某一条数据(也就是映射类的实例)从内存中删除而已,并没有对数据库有任何操作。

  1. session.rollback()