SQLAlchemy连接MySQL及记录的查询、更新、删除、多表关联查询

SQLAlchemy是Python的ORM库,支持多种数据库。

建立连接

连接MySQL要用到Engine,Engine集成了连接池pool和方言Dialect(支持不通数据库的SQL语法),最后都统一成标准DBAPI。

from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://user:pass@localhost/db?charset=utf8mb4',
                       echo=True, pool_recycle=7200, pool_size=5, max_overflow=10, pool_timeout=30)

create_engine第一个参数是database url,用到了pymysql驱动。
参数echo用于打印执行中的关键日志,包括SQL执行语句。
pool_recycle表示connection空闲7200秒就会重新获取。
pool_size指定连接池大小。
max_overflow指定超过连接池大小的最大数。
pool_timeout获取连接的超时阈值。
poolclass设置为NullPool,禁用连接池,session.Close()之后会立即断开数据库连接。

报错:Lost connection to MySQL server during query

2013, 'Lost connection to MySQL server during query 
([Errno 104] Connection reset by peer)

设置pool_pre_ping=Truepool_recycle可以每次执行都查看连接是否可用。
pool_recycle的值 应该比mysql中设置的 interactive_timeoutwait_timeout 值小才有效。
pool_timeout的值(默认10s) 应该比 mysql的 connect_timeout值 小或者等于。

SHOW GLOBAL VARIABLES LIKE '%timeout%';

@等特殊字符的处理

urllib.parse.quote_plus编码@特殊字符。

from urllib import parse
from sqlalchemy import create_engine
 
user = "root"
password = "******@108"
host = "127.0.0.1"
db = "db_name"
 
pwd = parse.quote_plus(password)
 
engine = create_engine(f"mysql+pymysql://{user}:{pwd}@{host}:3306/{db}?charset=utf8")
 

建立映射

sqlalchemy把表table映射成model class,把字段field映射成column,把记录record映射成实例instance。

手动创建映射

from sqlalchemy.sql.schema import Column
from sqlalchemy.types import BigInteger, String, Integer

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = Column(BigInteger, primary_key=True)
    name = Column(String(255))
    age = Column(Integer)
    gender = Column(String(255))

另外可以使用sqlacodegen(pip install sqlacodegen)自动生成model:

sqlacodegen mysql+pymysql://user:password@localhost/test --outfile=models.py --tables users
# coding: utf-8
from sqlalchemy import Column, String
from sqlalchemy.dialects.mysql import BIGINT, INTEGER
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
metadata = Base.metadata


class User(Base):
    __tablename__ = 'users'

    id = Column(BIGINT(20), primary_key=True)
    name = Column(String(255, 'utf8_unicode_ci'))
    age = Column(INTEGER(11))
    gender = Column(String(255, 'utf8_unicode_ci'))

参考类型:

类型介绍
Integer/BigInteger/SmallInteger整型
Boolean布尔类型. Python 中表现为 True/False , 数据库根据支持情况, 表现为 BOOLEAN 或 SMALLINT . 实例化时可以指定是否创建约束(默认创建).
Date/DateTime/Time (timezone=False)日期类型, Time 和 DateTime 实例化时可以指定是否带时区信息
Interval时间偏差类型. 在 Python 中表现为 datetime.timedelta() , 数据库不支持此类型则存为日期
Enum (*enums, **kw)枚举类型, 根据数据库支持情况, SQLAlchemy 会使用原生支持或者使用 VARCHAR 类型附加约束的方式实现. 原生支持中涉及新类型创建, 细节在实例化时控制
Float浮点小数
Numeric (precision=None, scale=None, decimal_return_scale=None, …)定点小数, Python 中表现为 Decimal
LargeBinary (length=None)字节数据. 根据数据库实现, 在实例化时可能需要指定大小
PickleTypePython 对象的序列化类型
String (length=None, collation=None, …)字符串类型, Python 中表现为 Unicode , 数据库表现为 VARCHAR , 通常都需要指定长度
Unicode类似与字符串类型, 在某些数据库实现下, 会明确表示支持非 ASCII 字符. 同时输入输出也强制是 Unicode 类型
Text长文本类型, Python 表现为 Unicode , 数据库表现为 TEXT
UnicodeText参考 Unicode

自动创建映射

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql.schema import Table

Base = declarative_base()
metadata = Base.metadata
metadata.bind = engine


# class User(Base):
#     __table__ = Table('users', metadata, autoload=True)
class User(Base):
    __table__ = Table('users', metadata, autoload_with=engine)

设置autoload或autoload_with就可以自动生成映射,另外Base.metadata需要提前绑定engine。

查询

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)
session = Session()
query = session.query(User).filter(User.age >= 19).filter(User.name.like("王%"))
for user in query.all():
    print(user.age)

查询用到了Session对象,类似一个容器,容器里是identity map 的结构对象。
用filter过滤数据。

等值过滤器(==)

session.query(Account).filter(Account.user_name=='Mark') #判断字符串类型
session.query(Account).filter(Account.salary==2000) #判断数值类型

不等过滤器(!=、<、>、<=、>=)

session.query(Account).filter(Account.user_name !="mark" ) #不等于字符串类型
session.query(Account).filter(Account.salary !=2000) #不等于数值类型
session.query(Account).filter(Account.salary >2000) #大于过滤器
session.query(Account).filter(Account.salary <2000) #小于过滤器
session.query(Account).filter(Account.salary <=2000) #小于等于过滤器
session.query(Account).filter(Account.salary >=2000) #大于等于过滤器

模糊查询(like)

#查询所有名字包含字母i的用户,结果包括id为1、2、3、4的4条记录
session.query(Account).filter(Account.user_name.like('%i%'))

#查询所有title中以Manager结尾的用户,结果包括id为1、5的两条记录
session.query(Account).filter(Account.title.like('%Manager'))

#查询所有名字中以Da开头的用户,结果包括id为1、3的两条记录
session.query(Account).filter(Account.user_name.like('Da%'))

包括过滤器(in_)

#查询id不为1,3,5的记录,结果包含id为2,4的两条记录
session.query(Account).filter(~Account.id.in_([1,3,5]))
#查询工资不为2000、3000、4000的记录,结果包含id为5的1条记录
session.query(Account).filter(~Account.id.in_([2000,3000,4000]))
#查询所有title不为Engineer和Accountant记录,结果包括id为1、5的两条记录
session.query(Account).filter(~Account.title.in_(['Accountant','Engineer']))

判断是否为空(is NULL、is not NULL)

#查询salary为空值的记录,结果包含id为5的记录
#下面两方式效果相同
session.query(Account).filter(Account.salary==None)
session.query(Account).filter(Account,salary.is_(None))

#查询salary不为空值的记录,结果包含id为1、2、3、4的记录
#下面两方式效果相同
session.query(Account).filter(Account.salary!=None)
session.query(Account).filter(Account.salary.isnot(None))

非逻辑(~)

#查询id不为1、3、5的记录,结果包含id为2、4的两条记录
session.query(Account).filter(~Account.id.in_([1,3,5]))

#查询工资不为2000、3000、4000的记录,结果包含id为5的1条记录
session.query(Account).filter(~Account.id.in_([2000,3000,4000]))

#查询所有title不为Engineer和Accountant的记录,结果包括id为1、5的2条记录。
session.query(Account).filter(~Account.title.in(['Accountant','Engineer']))

与逻辑(and_)

#直接在filter中添加多个条件即表示与逻辑
session.query(Account).filter(Account.title=='Engineer',Account.salary=3000)

#用关机子and_进行逻辑查询
from sqlalchemy import and_
session.query(Account).filter(and_(Account.title=='Engineer',Account.salary=3000))

#通过多个filter的链接表示与逻辑
session.query(Account).filter(Account.title=='Engineer').filter(Account.salary=3000)

或逻辑(or_)

#引入或逻辑关键字or_
from sqlalchemy import or_

#查询title是Engineer或者salary为3000的记录,返回结果为id为1、2、3、4的记录
session.query(Account).filter(or_(Account.title=='Engineer',Account.salary=3000))

新增

user1 = User()
user1.name = "赵六"
user1.age = 21
user1.gender = "女"
session.add(user1)
session.commit()

先建立一个User实例,然后调用session的add方法,最后commit。

批量插入新增

bulk_save_objects方法

session = Session()
objects = [
    User(name="u1"),
    User(name="u2"),
    User(name="u3")]
session.bulk_save_objects(objects)

add_all方法

session = Session()
objects = [User(name="u1"), User(name="u2"), User(name="u3")]
session.add_all(objects)
session.commit()

更新

user2 = session.query(User).filter_by(name='赵六').first()
user2.gender = "男"
session.commit()

先查找到User实例,然后修改实例属性,最后调用session的commit修改数据库。

删除

user3 = session.query(User).filter_by(name='赵六').first()
session.delete(user3)
session.commit()

多表查询

Session = sessionmaker(bind=engine)
session = Session()
query = session.query(User, Address).join(Address, User.id == Address.user_id)
for user in query.all():
    print(user[0].name)
    print(user[1].add)

这里用了join方法

参考

http://sunnyingit.github.io/book/section_python/SQLalchemy-session.html

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要使用SQLAlchemy连接多个数据库并使用连接池,你可以创建多个连接池对象并为每个数据库创建一个独立的引擎。以下是一个示例代码,展示了如何使用SQLAlchemy连接连接多个MySQL数据库: ```python from sqlalchemy import create_engine from sqlalchemy.pool import QueuePool # 创建连接池1 pool1 = QueuePool( creator=lambda: mysql.connector.connect( host='localhost', database='database1', user='username1', password='password1' ), pool_size=5 ) # 创建连接池2 pool2 = QueuePool( creator=lambda: mysql.connector.connect( host='localhost', database='database2', user='username2', password='password2' ), pool_size=5 ) # 创建SQLAlchemy引擎1 engine1 = create_engine('mysql+mysqlconnector://', creator=pool1.get) # 创建SQLAlchemy引擎2 engine2 = create_engine('mysql+mysqlconnector://', creator=pool2.get) # 将DataFrame写入数据库1的表 df.to_sql(name='table1', con=engine1, if_exists='replace', index=False) # 将DataFrame写入数据库2的表 df.to_sql(name='table2', con=engine2, if_exists='replace', index=False) ``` 在上面的代码中,你需要将`database1`、`username1`、`password1`替换为第一个数据库的实际信息,将`database2`、`username2`、`password2`替换为第二个数据库的实际信息。 通过创建多个连接池对象和引擎对象,你可以连接多个MySQL数据库,并使用连接池管理数据库连接。 希望这可以满足你的需求!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小龙在山东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值