首页 > 代码库 > SqlAlchemy ORM

SqlAlchemy ORM

SQLAlchemy

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

技术分享

Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:

MySQL-Python
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
  
pymysql
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
  
MySQL-Connector
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
  
cx_Oracle
    oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
  
更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html

使用 Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 进行数据库操作。Engine使用Schema Type创建一个特定的结构对象,之后通过SQL Expression Language将该对象转换成SQL语句,然后通过 ConnectionPooling 连接数据库,再然后通过 Dialect 执行SQL,并获取结果。

创建表

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

engine = create_engine("mysql+pymysql://user02:user02@192.168.33.35:3306/aaa?charset=utf8", max_overflow=5)
# mysql+pymysql:固定格式
# user02:user02:用户名及密码
# @192.168.33.35:3306/
# aaa:数据库名字
# ?charset=utf8:支持utf8
Base = declarative_base()  # 生成orm基类


# 创建单表
class User(Base):
    __tablename__ = users  # 表名
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键自增
    name = Column(String(50), index=True, nullable=True)  # 创建索引并不能为空
    extra = Column(String(50))

    __table_args__ = (
        UniqueConstraint(id, name, name=uix_id_name),  # 联合唯一索引
        Index(ix_id_name, name, extra),  # 联合索引
    )


# 一对多
class Colour(Base):
    __tablename__ = colour  # 表名
    cid = Column(Integer, primary_key=True, autoincrement=True)
    colour = Column(String(20), server_default=red, unique=True)


class Dress(Base):
    __tablename__ = dress  # 表名
    did = Column(Integer, primary_key=True)
    name = Column(String(32), index=True, nullable=True)
    colour_id = Column(Integer, ForeignKey(Colour.cid))


# 多对多
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)


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))


def init_db():
    Base.metadata.create_all(engine)  # 创建表结构


init_db()

Foreignkey的2种写法的区别:

是用第一种写法,必须要注意顺序,如果是用第二种,就随意了

user_type_id = Column(Integer, ForeignKey(UserType.user_type_id))  # 使用这个写法,必须把UserType表放在前面
user_type_id = Column(Integer, ForeignKey(user_type.user_type_id))

也可以在类下面加上这个方法:

目的是在我们查询的时候,都显示的是方法,如果把该方法加入到相关类下面,返回的就是数据了

    def __repr__(self):
        tmp = %s - %s - %s - %s % (self.id, self.name, self.extra, self.num)
        return tmp

删除表

def drop_db():
    Base.metadata.drop_all(engine)

最基本的增删改查

add

Session = sessionmaker(bind=engine)
session = Session()
# 增(单条)
obj1 = User(name=test1, extra=test1)
session.add(obj1)  # 增加单条
session.commit()

# ============================================
# 增(多条)
session.add_all([
    User(name=test3, extra=test3),
    User(name=test4, extra=test4),
])
session.commit()

delete

# 删除
session.query(User).filter(User.id > 4, User.extra == d).delete()

session.commit()

update

session.query(User).filter(User.id > 4).update({User.name: test10})
session.query(User).filter(User.id > 4).update({User.extra: User.extra + "111"}, synchronize_session=False)  # 字符串拼接
session.query(User).filter(User.id > 4).update({User.num: User.num + 1}, synchronize_session="evaluate")  # 数字相加
session.commit()

select

ret = session.query(User).all()  # 已对象形式返回所有数据
ret = session.query(User.name, User.id).all()
ret = session.query(User).filter_by(name=a).all()
ret = session.query(User).filter_by(name=a).first()

进阶篇增删改查

select

ret = session.query(User).filter(User.id > 2, User.name == c).all()
ret = session.query(User).filter(User.id.between(1, 3), User.name == c).all()
ret = session.query(User).filter(User.id.in_([1, 3, 4])).all()
ret = session.query(User).filter(~User.id.in_([1, 3, 4])).all()
ret = session.query(User).filter(User.id.in_(session.query(User.id).filter_by(name=c))).all()  # 嵌套查询

and、or

需要先导入模块

from sqlalchemy import and_,or_
ret = session.query(User).filter(and_(User.id > 2, User.name == c)).all()
ret = session.query(User).filter(or_(User.id > 2, and_(User.name == c), User.extra != ‘‘)).all()

通配符

ret = session.query(User).filter(User.name.like(e%)).all()  # 查询已e开始的name字段
ret = session.query(User).filter(~User.name.like(e%)).all()

限制

ret = session.query(User)[1:4]  # 这个不需要all

排序

ret = session.query(User).order_by(User.name.desc()).all()  # 从高到低
ret = session.query(User).order_by(User.name.desc(), User.id.asc()).all()

groupby

需要先导入一个模块

from sqlalchemy.sql import func

连表操作

ret = session.query(Colour, Dress).filter(Colour.cid == Dress.colour_id).all()
print(ret)
for i in ret:
    print(i.name)
ret = session.query(Dress).join(Colour).all()  # 默认是inner join
ret = session.query(Dress).join(Colour, isouter=True).all()  # 默认是left join

sql = session.query(Dress.name, Colour.colour).join(Colour)  # 输出sql语句
print(sql)
a = session.query(Dress.name, Colour.colour).join(Colour).all()
print(a)

组合

q1 = session.query(User.name).filter(User.id > 4)
q2 = session.query(Colour.colour).filter(Colour.colour == red)
ret = q1.union(q2).all()  # 默认去重

q1 = session.query(User.name).filter(User.id > 4)
q2 = session.query(Colour.colour).filter(Colour.colour == red)
ret = q1.union_all(q2).all()  # 不去重

relationship

这个功能只是优化在你写代码过程中,进一步优化

一般情况下,relationship跟外键在一起,当用显示存在obj.col这个方式的时候,我们一般叫正向查找,当使用backref叫做反向查找

正向查找:

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

engine = create_engine("mysql+pymysql://user02:user02@192.168.33.35:3306/aaa?charset=utf8", max_overflow=5)

Base = declarative_base()  # 生成orm基类

# 一对多
class Colour(Base):
    __tablename__ = colour  # 表名
    cid = Column(Integer, primary_key=True, autoincrement=True)
    colour = Column(String(20), default=red, unique=True)


class Dress(Base):
    __tablename__ = dress  # 表名
    did = Column(Integer, primary_key=True)
    name = Column(String(32), index=True, nullable=True)
    colour_id = Column(Integer, ForeignKey(Colour.cid))
    # 与生成表结构无关,仅用于查询方便
    col = relationship("Colour", backref=‘uuu‘)

Session = sessionmaker(bind=engine)
session = Session()
ret = session.query(Dress).all()
for obj in ret:
    # obj代指Dress的每一行数据
    # obj.col代指group对象,封装了Group里面的所有数据
    print(obj.did, obj.name, obj.col.colour, obj.col.cid)

反向查找:

Session = sessionmaker(bind=engine)
session = Session()
obj = session.query(Colour).filter(Colour.colour == red).first()
print(obj.cid)
print(obj.colour)
print(obj.uuu)

 

 

 

 

MySql数据库常用命令

 

SqlAlchemy ORM