黑夜 发表于 2020-8-31 17:29:04

入门 SQLAlchemy

本帖最后由 黑夜 于 2020-8-31 17:40 编辑

SQLAlchemy是 Python 下的一款数据库对象关系映射(ORM)工具,能满足大多数数据库操作需求,同时支持多种数据库引擎(SQLite,MySQL,Postgresql,Oracle等)。所谓 ORM(Object Relational Mapper)可以理解为“将数据库中的表映射为程序中的类”,表中的一行即为类的一个实例。比如 Users 表映射为 User 类,表中的一行数据映射为 User() 实例。

SQLAlchemy 在 Web 开发中应用较多,但作为一个数据分析、数据挖掘人员,最好也能掌握这门灵活的数据库操作技术。它的主要优点有:


[*]对数据表的抽象,允许开发人员首先考虑数据模型,同时使得Python程序更加简洁易读。


[*]对各种数据库引擎的封装,使得开发人员在面对不同数据库时,只需要做简单修改即可,工作量大大减少



关于 SQLAlchemy 的学习

我个人觉得 SQLAlchemy 的学习难度会比 Django 的 Model 层难一些,因为一个最简单的例子也会有一些不太直观的地方,对于没用过的人来说,会比较难以理解。不过 SQLAlchemy 官网整理了一些比较不错的入门教程,是一个比较好的学习起点:Tutorials。另外,官方的Reference其实是一个很好的教程,讲了很多基本的概念,有助于理解SQLAlchemy的库的使用。Reference的地址是:http://docs.sqlalchemy.org/en/,还可以直接下载 PDF 版本。我个人建议大家直接阅读 Reference 即可,阅读顺序就按照 PDF 文件的章节编排顺序进行。虽然这个文档很长,但是我最后发现这么做是最节约时间的。

SQLAlchemy 的架构

先让我们来看一下 SQLAlchemy 这个库的总体架构,如下图(图来自官网)所示:



SQLAlchemy 这个库分为两层:


[*]上面这层是 ORM 层,为用户提供 ORM 接口,即通过操作 Python 对象来实现数据库操作的接口。
[*]下面这层是 Cor e层,这层包含了 Schema/Types, SQL Expression Language, Engine 这三个部分。
[*]最后,SQLAlchemy 还要依赖各个数据库驱动的 DBAPI 接口来实现对数据库服务的调用。DBAPI 是 Python 定义的数据库 API 的实现规范,具体见 PEP0249。



首先需要利用 pip 安装 SQLAlchemy(推荐使用 poetry管理依赖):
pip install SQLAlchemy

其次是在程序中通过代码连接到数据库:
engine = sqlalchemy.create_engine("mysql+pymysql://username:password@hostname/dbname", encoding="utf8", echo=True)

这里需要注意,不同的数据库,不同的数据库驱动,对应不同的连接字符串。具体可参考:。

这里还是以“撸代码,学知识”的形式学习这门技术。在我的代码中用到的是 MySQL 数据库,以及 PyMysq l驱动,并尽量多的写清楚注释。代码中主要展示如下功能:


[*] 创建 engine,并通过 engine 连接数据库。
[*] 利用 engine 连接数据库后的基本数据操作,包括事务中的批量提交和回滚操作。但这里没有用到ORM,不是重点(代码中利用"""进行了注释)。
[*] 利用 SQLAlchemy 构建数据模型 User和 Role。这里两者存在一对多、多对一的关系。同时利用数据模型构建数据库表。
[*] 利用 SQLAlchemy 中的 Session 对象进行基础的数据操作,包括增删改查等。Session对象可以记录和跟踪数据的变化,并提供强大的 ORM 功能。
[*] 利用 SQLAlchemy 中的 Session 对象进行一些高级数据操作,包括 distinct、limit、offset、scalar、count、average、sum、filter、group by、order by 等。
[*] 利用 SQLAlchemy 中的 orm 特性试验外键、关联属性、join操作等高级操作。这部分建议大家多看多实践一些,而且重点看一些 relationship、backref 等关键用法,代码中都有详细解释




为 SQLAlchemy 提供异步支持
pip install databases

实例代码:
class AioDataBase():
    async def __aenter__(self):
      db = databases.Database(DB_URL.replace('+pymysql', ''))
      await db.connect()
      self.db = db
      return db

    async def __aexit__(self, exc_type, exc, tb):
      if exc:
            traceback.print_exc()
      await self.db.disconnect()

SQLAlchemy常用数据类型:

[*]Integer:整形,映射到数据库中是int类型。
[*]Float:浮点类型,映射到数据库中是float类型。他占据的32位。
[*]Double:双精度浮点类型,映射到数据库中是double类型,占据64位。
[*]String:可变字符类型,映射到数据库中是varchar类型.
[*]Boolean:布尔类型,映射到数据库中的是tinyint类型。
[*]DECIMAL:定点类型。是专门为了解决浮点类型精度丢失的问题的。在存储钱相关的字段的时候建议大家都使用这个数据类型。并且这个类型使用的时候需要传递两个参数,第一个参数是用来标记这个字段总能能存储多少个数字,第二个参数表示小数点后有多少位。
[*]Enum:枚举类型。指定某个字段只能是枚举中指定的几个值,不能为其他值。在ORM模型中,使用Enum来作为枚举
[*]Date:存储时间,只能存储年月日。映射到数据库中是date类型。在Python代码中,可以使用datetime.date来指定
[*]DateTime:存储时间,可以存储年月日时分秒毫秒等。映射到数据库中也是datetime类型。在Python代码中,可以使用datetime.datetime来指定。示例代码如下:
[*]Time:存储时间,可以存储时分秒。映射到数据库中也是time类型。在Python代码中,可以使用datetime.time来至此那个。
[*]Text:存储长字符串。一般可以存储6W多个字符。如果超出了这个范围,可以使用LONGTEXT类型。映射到数据库中就是text类型。
[*]LONGTEXT:长文本类型,映射到数据库中是longtext类型。


Column 常用参数

[*]primary_key 如果设为True,这列就是表的主键

[*]unique 如果设为True,这列不允许出现重复的值

[*]index 如果设为True,这列创建索引,提升查询效率

[*]nullable 如果设为True,这列允许使用空值;如果设为False,这列不允许使用空值

[*]default 为这列定义默认值

[*]autoincrement        是否自增

[*]onupdate        更新时执行的
[*]name        数据库映射后的属性



增删改查(CURD)

CRUD 就是 CREATE, READ, UPDATE, DELETE,增删改查。这个也是 SQLAlchemy 中最常用的功能,而且都是通过上一小节中的session对象来使用的。我们这简单的介绍一下这四个操作,后面会给出官方文档的位置。

Create
在数据库中插入一条记录,是通过 session 的add()方法来实现的,你需要先创建一个映射类的实例,然后调用session.add()方法,然后调用session.commit()方法提交你的事务(关于事务,我们下面会专门讲解):

new_person = Person(name='new person')
session.add(new_person)
session.commit()
Delete

删除操作和创建操作差不多,是把一个映射类实例传递给 session.delete() 方法。

Update
更新一条记录需要先使用查询操作获得一条记录对应的对象,然后修改对象的属性,再通过 session.add() 方法来完成更新操作。

Read
查询操作,一般称为 query,在 SQLAlchemy 中一般是通过 Query 对象来完成的。我们可以通过 session.query() 方法来创建一个 Query 对象,然后调用 Query 对象的众多方法来完成查询操作。

事务
使用 session,就会涉及到事务,我们的应用程序也会有很多事务操作的要求。当你调用一个 session 的方法,导致 session 执行一条 SQL 语句时,它会自动开始一个事务,直到你下次调用 session.commit() 或者 session.rollback(),它就会结束这个事务。你也可以显示的调用 session.begin() 来开始一个事务,并且 session.begin() 还可以配合 Python 的 with 来使用。

会话, CRUD, 事务的小结
上面关于 session, CRUD 和事务的内容写的比较少,因为这些功能的内容很多,而且官方文档也写得很全面,本文就不做一些重复说明了。

官方文档中关于 CRUD 操作的教程




转之网络,有修改

https://diabloneo.github.io/2016/01/06/learn-openstack-dev-skill-by-demo-06/

余平晨 发表于 2020-9-4 16:44:32

sinXin 发表于 2021-10-8 17:01:46

最近在学django ORM模型,就感觉有点吃力。

dwanxp 发表于 2022-3-28 08:19:42

是啊 ,很不错的教材啊 。。。。。。。。。。。。。。
页: [1]
查看完整版本: 入门 SQLAlchemy