python之SQLAlchemy的使用

本文参考官方文档,如果错误请指出

 1、安装SQLAlchemy并且检查版本

1.1、安装模块
pip3 install SQLAlchemy

1.2、检查版本
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.3.11'
安装模块与检查版本

 2、数据库连接的创建

from sqlalchemy.engine import create_engine
# echo=True表示日志打印出来
engine = create_engine("mysql://mysql_username:mysql_password@IP地址:端口/数据库名字?charset=utf8", encoding='utf-8', echo=False)

注意:
  其它数据库配置和更多的create_engine参数方式,请参数官网:https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine
创建数据库引擎

 3、声明类与数据库表的映射关系

from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

#以User表为例
class User(Base):
    # 数据库表名
    __tablename__ = 'users'

    # 这个MySQL使用的主键
    # id = Column(Integer, primary_key=True, autoincrement=True)
    # 这个是Oracle使用的主键定义方法,MySQL也通过,推荐使用这个,数据库更换时,可以不用修改代码
    id = Column(Integer, Sequence('user_id_seq'), primary_key=True)

    name = Column(String(30))
    fullname = Column(String(30))
    nickname = Column(String(30))

    def __repr__(self):
        """命令行运行时,打印对象显示的值调用"""
        return "" % (self.name, self.fullname, self.nickname)
User_model.py

 4、创建数据库连接的会话

from sqlalchemy.engine import create_engine
from sqlalchemy.orm import sessionmaker

# echo=True表示日志打印出来
engine = create_engine("mysql://django:[email protected]:3306/testDatabase", encoding='utf-8', echo=False)

Session = sessionmaker(bind=engine)  # 产生会话
Session.configure(bind=engine)  # 往Session配置可用的会话引擎
session = Session()
SQLAlchemy_session

 5、数据库数据迁移

# 删除所有表
Base.metadata.drop_all(engine)

# 创建所有表
Base.metadata.create_all(engine)
删除与创建所有表的函数

 6、简单的单表增删改查示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import sessionmaker

# echo=True表示日志打印出来
engine = create_engine("mysql://django:[email protected]:3306/day120?charset=utf8", encoding='utf8', echo=False)

Base = declarative_base()

class User(Base):
    # 数据库表名
    __tablename__ = 'users'

    # 字段
    id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
    name = Column(String(30))
    fullname = Column(String(30))
    nickname = Column(String(30))

    def __repr__(self):
        """命令行运行时,打印对象显示的值调用"""
        return "" % (self.name, self.fullname, self.nickname)


def create_all_table():
    # 创建所有表
    Base.metadata.create_all(engine)


def drop_all_table():
    # 删除所有表
    Base.metadata.drop_all(engine)


Session = sessionmaker(bind=engine)  # 产生会话
Session.configure(bind=engine)  # 往Session配置可用的会话引擎
session = Session()

# 1、插入数据
# 1.1、一条数据
ed_user = User(name='阿三', fullname='张三', nickname='张大嘴')
session.add(ed_user)
session.commit()

# 1.2、批量插入数据
session.add_all([
    User(name='李一', fullname='li One', nickname='小李子'),
    User(name='张一', fullname='zhang One', nickname='小张子'),
    User(name='陈一', fullname='chen One', nickname='小陈子')
])
session.commit()

# 2、查询数据
# 2.1、返回对象
user_obj = session.query(User).filter_by(name='阿三').first()
print(user_obj)

# 2.2、返回列表
user = session.query(User).filter(User.name == '阿三')

print('打印出SQL语句', user)
# SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.nickname AS users_nickname
# FROM users
# WHERE users.name = %s
print('user.all()', user.all())  # []

# 3、删除数据
delete_user_obj = session.query(User).filter(User.name == '张一').delete()
session.commit()

# 4、修改数据
session.query(User).filter(User.name == '阿三').update({User.nickname: '张大嘴'})
session.commit()
sqlalchemy_add_delete_update_query.py

 7、SQLAlchemy  session.dirty 和session.new的理解

#1、session.new的案例,主要作用:打印出已增加的数据,但是未提交至数据库的数据
# session.add_all([
#     User(name='wendy', fullname='Wendy Williams', nickname='windy'),
#     User(name='mary', fullname='Mary Contrary', nickname='mary'), ])
#
# #打印出需要新增加的数据
# print(session.new)
"""
IdentitySet([, ])
"""

#2、session.dirty案例,主要作用:打印出已增加到session中,未提交至数据库,但是在这个过程中又被修改的数据,也叫脏读
ed_user = User(name='ed', fullname='Ed Jones', nickname='edsnickname')
session.add(ed_user)

#从未提交的数据,查询出数据的对象
our_user = session.query(User).filter_by(name='ed').first()

ed_user.nickname = '印度阿三'
print(session.dirty)
"""
IdentitySet([])
"""
session.new与session.dirty的示例

 8、SQLAlchemy  session级别的事务回滚

# 从数据库中查询出来一条数据的对象
ed_user = session.query(User).filter(User.name == '阿三').first()
ed_user.name = '张三三'  # 在内存中修改ed_user对象的名字,因为session里面是指向的内存地址,所以这里一修改,session里面的name也会随着变

fake_user = User(name='李四', fullname='李大四', nickname='李Boss')
session.add(fake_user)

users = session.query(User).filter(User.name.in_(['张三三', '李四'])).all()
print(users)
"""
[, 
]
"""

# 回滚到查询没有修改的数据
session.rollback()
print(ed_user.name)  # 阿三

users = session.query(User).filter(User.name.in_(['阿三', '李四'])).all()
print(users)
# []
rollback

 9、SQLAlchemy  查询(Query)示例(官方示例,推荐练习)

###############################################################################
# 1、查询结果排序显示出来
users = session.query(User).order_by(User.id)
for instance in users:
    print(instance.id, instance.name, instance.nickname,instance.fullname)
"""
1 阿三 张大嘴 张三
2 李一 小李子 li One
20 李一1 小李子 li One
21 张一1 小张子 zhang One
22 陈一1 小陈子 chen One
"""
###############################################################################
# 2、查询结果,显示指定的列
users = session.query(User.name, User.fullname)
for instance in users:
    print(instance.name, instance.fullname)
"""
阿三 张三
李一 li One
李一1 li One
张一1 zhang One
陈一1 chen One
"""
###############################################################################
# 3、查询所以数据+某一列数据
users = session.query(User, User.name)
for instance in users:
    print(instance.User, instance.name)
"""
 阿三
 李一
 李一1
 张一1
 陈一1
"""
###############################################################################
# 4、查询数据结果,并且对列增加标签label,方便python取值
users = session.query(User.name.label('name_label'))
for instance in users:
    print(instance.name_label)
"""
阿三
李一
李一1
张一1
陈一1
"""
###############################################################################
# 5、查询数据,给数据库User表每一个列增加别名,下面的示例就别名是:user_alias_列名
from sqlalchemy.orm import aliased

user_alias = aliased(User, name='user_alias')
users = session.query(user_alias, user_alias.name).all()
for instance in users:
    print(instance.user_alias)
"""





"""
###############################################################################
# 7、分页Limit查询
users = session.query(User).order_by()[0:2]
for instance in users:
    print(instance)
"""


"""
###############################################################################
# 8、filter_by使用关键字参数查询
users = session.query(User).filter_by(fullname='li One').all()
for instance in users:
    print(instance)
"""


"""
# 与上面filter_by相同功能示例
users = session.query(User).filter(User.fullname == 'li One').all()
for instance in users:
    print(instance)
"""


"""
###############################################################################
# 9、多层filter()查询,是and关系
users = session.query(User).filter(User.fullname == 'li One').filter(User.name == '李一1').all()
for instance in users:
    print(instance)
"""

"""
SQLAlchemy_Query

 10、普通过滤操作符(官方示例,推荐练习)

# 1、相等(==)
user_obj = session.query(User).filter(User.name=='阿三').first()
print(user_obj)
# 
#####################################################################
# 2、不相等(!=)
users = session.query(User).filter(User.name != '阿三').all()
for instance in users:
    print(instance)
"""




"""
#####################################################################
# 3、LIKE模糊查询
users = session.query(User).filter(User.nickname.like('%大%'))
for instance in users:
    print(instance)
# 
#####################################################################
# 4、怱略大小写的LIKE模糊查询
users = session.query(User).filter(User.fullname.ilike('%o%'))
for instance in users:
    print(instance)
"""


"""
#####################################################################
# 5、包含(in)
# 5.1、通过列表组装单列的查询
users = session.query(User).filter(User.fullname.in_(['chen ene', 'zhang ene']))
for instance in users:
    print(instance)
"""


"""

# 5.2、通过元组组装,多列混合的查询
from sqlalchemy import tuple_

# in_里面一个元组,对应tuple_条件列数据的过滤
users = session.query(User).filter(tuple_(User.name, User.fullname).in_([('张一1', 'zhang ene'), ('zhang ene','张三')]))
for instance in users:
    print(instance)
"""

"""
#####################################################################
# 6、不包含(not in)
users = session.query(User).filter(~User.nickname.in_(['张大嘴','小李子']))
for instance in users:
    print(instance)
"""


"""
#####################################################################
# 7、过滤行数据不能为空(is not null 或 != none)
users = session.query(User).filter(User.nickname != None)
for instance in users:
    print(instance)
# 或者
users = session.query(User).filter(User.nickname.isnot(None))
for instance in users:
    print(instance)
"""


"""
#####################################################################
# 8、且(and)
# 方法1、导and_包组装
from sqlalchemy import and_
users = session.query(User).filter(and_(User.name=='阿三',User.fullname=='张三'))

# 方法2、默认多个参数就是and关系
users = session.query(User).filter(User.name=='阿三',User.fullname=='张三')

# 方法3、多个filter()方法连接
users = session.query(User).filter(User.name == '阿三').filter(User.fullname == '张三')

for instance in users:
    print(instance)
"""

"""
#####################################################################
# 9、或(or)
from sqlalchemy import or_
users=session.query(User).filter(or_(User.name=='阿三',User.name=='陈一1'))
for instance in users:
    print(instance)
"""


"""
#####################################################################
# 10、模糊查询(contains)
users = session.query(User).filter(User.name.contains(''))
for instance in users:
    print(instance)
"""


"""
Common_Filter_Operators

 11、SQLAlchemy  查询返回值的介绍(官方示例,推荐了解)

# 1、返回list
user_list = session.query(User).all()
print(user_list)
"""
[, 
, 
, 
, 
]
"""
#########################################################################################
# 2、返回对象
user_obj = session.query(User).first()
print(user_obj)
"""

"""
#########################################################################################
# 3、单独查询一行,如果存在则返回对象,不存在抛出sqlalchemy.orm.exc.NoResultFound异常
user_obj = session.query(User).filter(User.id == 1).one()
print(user_obj)
"""

"""
#########################################################################################
# 4、单独查询一行,如果存在则返回对象,不存在返回None
user_obj = session.query(User).filter(User.id == '222').scalar()
print(user_obj)
"""
None
"""
Returning_Lists_and_Scalars

 12、SQLAlchemy  手写SQL语句查询

# 1、手写SQL条件查询
from sqlalchemy import text
users = session.query(User).filter(text("id>20")).all()
for instance in users:
    print(instance)
"""


"""
################################################################################
# 2、手写SQL+条件组合+params()参数格式化
users = session.query(User).filter(text("name=:name and fullname=:fullname")).params(name="阿三", fullname='张三').all()
for instance in users:
    print(instance)
"""

"""
################################################################################
# 3、手写完整的SQL语句查询所有列
from sqlalchemy import text

users = session.query(User).from_statement(text("SELECT * FROM users where name=:name")).params(name='李一1').all()
for instance in users:
    print(instance)
"""

"""
################################################################################
# 4、手写完整的SQL语句查询指定的列
from sqlalchemy import text

stmt = text("SELECT name, id, nickname ""FROM users where name=:name")
stmt = stmt.columns(User.name, User.id, User.nickname)
users = session.query(User).from_statement(stmt).params(name='李一').all()
for instance in users:
    print(instance)
"""

"""
Using_Textual_SQL

 13、SQLAlchemy 分组(group by)计数的示例

# 1、分组后,再计数
from sqlalchemy import func
users = session.query(func.count(User.nickname), User.nickname).group_by(User.nickname).all()
print(users)
"""
[(1, '小张子'), (2, '小李子'), (1, '小陈子'), (1, '张大嘴')]
"""
###################################################################################
# 2、计算表中所有列数据行记录总数
from sqlalchemy import func

user_count = session.query(func.count('*')).select_from(User).scalar()
print(user_count)
"""
5
"""
###################################################################################
# 3、如果使用主键来计数的话,可以不加select_from(User)
from sqlalchemy import func

user_count = session.query(func.count(User.id)).scalar()
print(user_count)
"""
5
"""
Counting

 14、SQLAlchemy 一对多(FK),增删改查示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import sessionmaker

# echo=True表示日志打印出来
engine = create_engine("mysql://django:[email protected]:3306/databaseName?charset=utf8", encoding='utf8', echo=False)

Base = declarative_base()


class User(Base):
    # 数据库表名
    __tablename__ = 'users'

    # 字段
    id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
    name = Column(String(30))
    fullname = Column(String(30))
    nickname = Column(String(30))

    def __repr__(self):
        """命令行运行时,打印对象显示的值调用"""
        return "" % (self.name, self.fullname, self.nickname)


from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship


class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
    email_address = Column(String(30), nullable=False)
    user_id = Column(Integer, ForeignKey('users.id',
                                         ondelete='CASCADE'))  # ondelete='CASCADE' : FK级联的配置,如果修改或删除,会清理关联数据,不需要,可以不用填写

    # 外键生成在addresses表
    user = relationship("User", back_populates="addresses")

    def __repr__(self):
        return "" % self.email_address


# 给User类增加外键的关系
User.addresses = relationship("Address", order_by=Address.id, back_populates="user", cascade="all, delete-orphan",
                              passive_deletes=True)  # cascade="all, delete-orphan",passive_deletes=True,FK级联的配置,不需要,可以不用填写


def create_all_table():
    # 创建所有表
    Base.metadata.create_all(engine)


def drop_all_table():
    # 删除所有表
    Base.metadata.drop_all(engine)


# 数据迁移,创建表
# drop_all_table()
# create_all_table()

Session = sessionmaker(bind=engine)  # 产生会话
Session.configure(bind=engine)  # 往Session配置可用的会话引擎
session = Session()
######################################################################################################
# 1、FK数据的增加
jack = User(name='jack', fullname='Jack Bean', nickname='gjffdd')
jack.addresses = [
    Address(email_address='[email protected]'),
    Address(email_address='[email protected]')
]
session.add(jack)
session.commit()
######################################################################################################
# 2、FK数据查询
user_obj = session.query(User).filter(User.name == 'jack').one()
print(user_obj)
print(user_obj.addresses)
"""

[, ]
"""
######################################################################################################
# 3、FK数据修改
user_obj = session.query(User).filter(User.name == 'jack').one()
adress1 = Address(email_address='[email protected]')
user_obj.addresses = [adress1, ]
session.commit()
print(user_obj.addresses)

######################################################################################################
# 4、FK删除数据
session.query(User).filter(User.name == 'jack').delete()
session.commit()
fk_add_update_select_delete(包含 FK级联的配置)

 15、SQLAlchemy 一对多(FK)为示例,通用的join查询

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import sessionmaker

# echo=True表示日志打印出来
engine = create_engine("mysql://django:[email protected]:3306/day120?charset=utf8", encoding='utf8', echo=False)

Base = declarative_base()

class User(Base):
    # 数据库表名
    __tablename__ = 'users'

    # 字段
    id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
    name = Column(String(30))
    fullname = Column(String(30))
    nickname = Column(String(30))

    def __repr__(self):
        """命令行运行时,打印对象显示的值调用"""
        return "" % (self.name, self.fullname, self.nickname)

from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship


class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
    email_address = Column(String(30), nullable=False)
    user_id = Column(Integer, ForeignKey('users.id',
                                         ondelete='CASCADE'))  # ondelete='CASCADE' : FK级联的配置,如果修改或删除,会清理关联数据,不需要,可以不用填写

    # 外键生成在addresses表
    user = relationship("User", back_populates="addresses")

    def __repr__(self):
        return "" % self.email_address


# 给User类增加外键的关系
User.addresses = relationship("Address", order_by=Address.id, back_populates="user", cascade="all, delete-orphan",
                              passive_deletes=True)  # cascade="all, delete-orphan",passive_deletes=True,FK级联的配置,不需要,可以不用填写


def create_all_table():
    # 创建所有表
    Base.metadata.create_all(engine)


def drop_all_table():
    # 删除所有表
    Base.metadata.drop_all(engine)

# 数据迁移,创建表
# drop_all_table()
# create_all_table()

Session = sessionmaker(bind=engine)  # 产生会话
Session.configure(bind=engine)  # 往Session配置可用的会话引擎
session = Session()

# 1、自已建立关联关系查询
result = session.query(User, Address).filter(User.id == Address.user_id).filter(
    Address.email_address == '[email protected]')
print(result)
for u, a in result:
    print(u, a)
###################################################################################################
# 2、join
# 2.1、join之字符串关联关系,addresses是User,relationship实例名字
result = session.query(User).join('addresses').filter(Address.email_address == '[email protected]').all()

# 2.2、join之指明外键关联值,addresses是User,relationship实例名字
result = session.query(User).join(Address,User.addresses).filter(Address.email_address == '[email protected]').all()

# 2.3、join之指定从左到右的关系
result = session.query(User).join(User.addresses).filter(Address.email_address == '[email protected]').all()

# 2.4、join之明确条件关联
result = session.query(User).join(Address, User.id == Address.user_id).filter(Address.email_address == '[email protected]').all()
for instance in result:
    print(instance)
###################################################################################################
# 3、若要控制join关联表的位置,可以使用select_from(table_class),表示放在第一的位置
query = session.query(User, Address).select_from(Address).join(User)
print(query)
"""
SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.nickname AS users_nickname, addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id 
FROM addresses(放在内连接的第一个位置) INNER JOIN users ON users.id = addresses.user_id
"""
Querying_with_Joins

 16、SQLAlchemy 一对多(FK)为示例,别名的查询,子查询等(少用)

# 1、别名的查询
# 当查询多个表时,如果同一表需要不止一次引用,SQL通常要求该表使用另一个名称进行别名,以便将其与该表的其他事件区分开来。
# 查询最显式地支持使用别名结构。下面我们将两次连接到Address实体,以找到同时具有两个不同电子邮件地址的用户:
from sqlalchemy.orm import aliased

adalias1 = aliased(Address)
adalias2 = aliased(Address)
result = session.query(User.name, adalias1.email_address, adalias2.email_address).\
    join(adalias1,User.addresses).\
    join(adalias2, User.addresses).\
    filter(adalias1.email_address == '[email protected]').\
    filter(adalias2.email_address == '[email protected]')

for username, email1, email2 in result:
    print(username, email1, email2)


# 2、子查询
from sqlalchemy.sql import func
stmt = session.query(Address.user_id, func.count('*').\
        label('address_count')).\
        group_by(Address.user_id).subquery()

for u, count in session.query(User, stmt.c.address_count).\
    outerjoin(stmt, User.id==stmt.c.user_id).order_by(User.id):
    print(u, count)

#3、从子查询中选择实体,即利用别名查询出结果,再进行join操作
from sqlalchemy.orm import aliased

stmt = session.query(Address).filter(Address.email_address != '[email protected]').subquery()

adalias = aliased(Address, stmt)
for user, address in session.query(User, adalias).join(adalias, User.addresses):
    print(user, address)
代码

 

 

 

 

持续更新...

 

你可能感兴趣的:(python之SQLAlchemy的使用)