SQLAlchemy学习笔记(一)
为什么要使用SQLAlchemy?
将你的代码抽象出来不依赖与数据库的类型和某种数据库自身的的独特性,SQLAlchemy提供了强大又通用的语句和类型,你不在需要考虑你所选用数据库的实现及其厂商。SQLAlchemy同样使得将数据逻辑从Oracle或者PostgreSQL到你的应用程序的数据库或者其他数据仓库。它将将对数据库的操作在提交给数据库之前进行了统一的规范和转义。这样就避免了一些常见的问题例如数据库注入攻击。
SQLAlchemy通过两种主要的数据库访问方式提供了强大的灵活性:SQL表达式和ORM。这些方式可以单独使用也可以结合使用,完全取决于你的喜好和应用程序的需要。
SQLAlchemy Core和 SQL Expression Language
SQL表达式是一种比较Pythonic的方式取代原始的SQL语句,它是一个对原始SQL语言的初级抽象,虽然聚焦于具体的数据库,然而,通过对多数的后端数据库提供了统一的语言实现了访问方式的统一。
ORM
SQLAlchemy ORM类似于你在其他语言中可能遇到的许多其他对象关系映射器(ORM)。它关注于应用程序的领域模型,并利用工作模式单元来维护对象状态。它还在SQL表达式语言之上提供了高级抽象,使用户能够以更习惯的方式工作。您可以混合使用ORM和SQL表达式语言来创建非常强大的应用程序。ORM利用了一个声明式系统,该系统与许多其他ORM(如Ruby on Rails中的ORM)使用的活动记录系统类似。
虽然ORM非常有用,但您必须记住,在关联类的方式和底层数据库关系的工作方式之间是有区别的。在第6章中,我们将更全面地探讨这种方法如何影响您的实现。
在SQLAlchemy Core和ORM之间如何选择?
在开始使用SQLAlchemy构建应用程序之前,您需要决定是主要使用ORM还是Core。选择SQLAlchemy Core或ORM作为应用程序的主要数据访问层通常取决于几个因素和个人偏好。
这两种模式使用的语法略有不同,但是Core和ORM之间最大的区别是将数据视为模式或业务对象。SQLAlchemy Core有一个以模式为中心的视图,它与传统SQL一样,主要关注表、键和索引结构。SQLAlchemy Core在数据仓库、报告、分析和其他场景中非常出色,在这些场景中,能够严格控制查询或对未建模的数据进行操作非常有用。强大的数据库连接池和结果集优化非常适合处理大量数据,甚至在多个数据库中也是如此。
但是,如果您希望更多地关注领域驱动的设计,ORM将在元数据和业务对象中封装大部分底层模式和结构。这种封装可以使数据库交互更像普通的Python代码。大多数常见的应用程序都适合以这种方式建模。它也可以是引入领域驱动设计的一种非常有效的方法,将SQLAlchemy引入到遗留应用程序中,或者在整个应用程序中散布原始SQL语句。微服务还受益于底层数据库的抽象,允许开发人员只关注正在实现的流程。
但是,由于ORM是在SQLAlchemy Core之上构建的,所以您可以使用它处理Oracle数据仓库和Amazon Redshift等服务的能力,就像它与MySQL交互一样。当您需要组合业务对象和存储的数据时,这对于ORM来说是一个极好的补充。
这里有一个快速清单,可以帮助你决定哪种选择最适合你:
如果您使用的框架已经内建了ORM,但希望添加更强大的报表,请使用Core。
如果您希望以更以模式为中心的视图(如SQL中使用的)查看数据,请使用Core。
如果您有不需要业务对象的数据,请使用Core。
如果您将数据视为业务对象,请使用ORM。
如果您正在构建一个快速原型,请使用ORM。
如果您的需求组合确实可以利用业务对象和其他与问题领域无关的数据,请同时使用它们!
现在,您已经了解了SQLAlchemy的结构以及Core和ORM之间的区别,我们已经准备好安装并开始使用SQLAlchemy来连接数据库。
SQLAlchemy的安装
默认情况下,SQLAlchemy将支持SQLite3,不需要额外的驱动程序;但是,需要一个使用标准Python DBAPI (PEP-249)规范的附加数据库驱动程序来连接到其他数据库。这些DBAPI为每个数据库服务器使用的dialect提供了基础,并且通常支持在不同数据库服务器和版本中看到的独特特性。虽然许多数据库可以使用多个dbapi,但是下面的说明主要针对最常见的数据库:
PostgreSQL
Psycopg2提供了对PostgreSQL版本和特性的广泛支持,可以与pip install Psycopg2一起安装。
MySQL
PyMySQL是我用来连接MySQL数据库服务器的首选Python库。它可以与pip安装pymysql一起安装。SQLAlchemy中的MySQL支持要求MySQL版本4.1或更高,这是由于该版本之前密码的工作方式。此外,如果特定的语句类型仅在MySQL的某个版本中可用,SQLAlchemy不提供在语句不可用的MySQL版本上使用这些语句的方法。如果SQLAlchemy中的某个组件或函数在您的环境中不起作用,那么检查MySQL文档是很重要的。
其他类型
SQLAlchemy还可以与Drizzle、Firebird、Oracle、Sybase和Microsoft SQL Server一起使用。该社区还为许多其他数据库提供了外部dialect,如IBM DB2、Informix、Amazon Redshift、EXASolution、SAP SQL Anywhere、Monet等。
现在可以安装SQLAlchemy
pip install -U sqlalchemy
检查安装结果:目前最新的发行版本是1.2.15,
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.2.15'
>>>
连接一个数据库
要连接到数据库,我们需要创建一个SQLAlchemy引擎。SQLAlchemy引擎创建到数据库的公共接口来执行SQL语句。它通过包装数据库连接池和dialect来实现这一点,这些连接池和dialect可以协同工作,提供对后端数据库的统一访问。这使我们的Python代码不必担心数据库或dbapi之间的差异。
SQLAlchemy提供了一个函数来为我们创建一个引擎,该引擎提供了一个连接字符串和一些额外的关键字参数。连接字符串是一种特殊格式的字符串,它提供:
数据库类型(Postgres, MySQL等)
除非数据库类型是默认的(Psycopg2、PyMySQL等),否则使用dialect。
可选身份验证细节(用户名和密码)
数据库的位置(数据库服务器的文件或主机名)
可选的数据库服务器端口,不指定则根据所选数据库类型连接其常规的默认端口
可选的数据库名称
SQLite数据库连接字符串让我们表示特定的文件或存储位置。示例P-1定义了一个名为cookies的SQLite数据库文件。db通过第二行中的相对路径存储在当前目录中,第三行是内存中的数据库,第四行(Unix)和第五行(Windows)是文件的完整路径。在Windows上,连接字符串看起来像engine4;除非您使用原始字符串(r”),否则需要使用\进行适当的字符串转义。
示例P-1:创建一个连接SQLite的engine
from sqlalchemy import create_engine
engine = create_engine('sqlite:///cookies.db')
engine2 = create_engine('sqlite:///:memory:')
engine3 = create_engine('sqlite:////home/cookiemonster/cookies.db')
engine4 = create_engine('sqlite:///c:\\Users\\cookiemonster\\cookies.db')
提示:create_engine只是创建了一个engine实例,但是它并不会立即去连接数据库,只有在需要连接数据库的操作触发后,engine才会去连接数据库,譬如一个查询操作。
让我们为名为mydb的本地PostgreSQL数据库创建一个引擎。我们首先从基本sqlalchemy包导入create_engine函数。接下来,我们将使用该函数构造一个引擎实例。在示例P-2中,您会注意到我使用postgresql+psycopg2作为连接字符串的引擎和dialect组件,即使只使用postgres也可以工作。这是因为我更喜欢显式而不是隐式,就像Python之禅推荐的那样。
示例P-2:创建一个连接本地PostgreSQL的engine
from sqlalchemy import create_engine
engine = create_engine('postgresql+psycopg2://username:password@localhost:5432/mydb')
现在让我们看一下远程服务器上的MySQL数据库。您将注意到,在示例P-3中,在连接字符串之后,我们有一个关键字参数pool_recycle,用于定义循环使用连接的频率。
示例P-3:创建一个连接远程MySQL数据库的engine
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://cookiemonster:chocolatechip@mysql01.monster.'
'internal/cookies', pool_recycle=3600)
注意:默认情况下,MySQL会关闭空闲时间超过8小时的连接。要解决这个问题,在创建引擎时使用pool_recycle=3600,如示例P-3所示。
一些在创建engine时可选的参数如下:
-
echo
这将记录引擎处理的操作,如SQL语句及其参数。它默认为false。
-
encoding
这定义了SQLAlchemy使用的字符串编码。它默认为utf-8,大多数DBAPI默认支持这种编码。这并不定义后端数据库本身使用的编码类型。
-
isolation_level
这指示SQLAlchemy使用特定的隔离级别。例如,带有Psycopg2的PostgreSQL有READ COMMITTED、READ UNCOMMITTED、REPEATABLE READ、SERIALIZABLE和AUTOCOMMIT,默认情况下是READ COMMITTED。PyMySQL具有相同的选项,默认为InnoDB数据库的可重复读取。
注意:使用isolation_level关键字参数将为任何给定的DBAPI设置隔离级别。这与通过连接字符串中的键-值对(如支持该方法的Psycopg2)来实现相同。
-
pool_recyle
这将定期回收或超时数据库连接。由于前面提到的连接超时,这对于MySQL非常重要。它的默认值是-1,这意味着没有超时。
一旦初始化了引擎,就可以实际打开到数据库的连接。这是通过调用引擎上的connect()方法实现的,如下所示:
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://cookiemonster:chocolatechip'
'@mysql01.monster.internal/cookies', pool_recycle=3600)
connection = engine.connect()
现在我们已经有了数据库连接,可以开始使用SQLAlchemy Core或ORM。