SQLAlchemy和数据库

SQLAlchemy是Python编程语言下的一款开源软件,使用MIT许可认证,SQLAlchemy提供了SQL工具包以及对象关系映射器(ORM),这样SQLAlchemy能让Python开发人员简单灵活的运用SQL操作后台数据库。
SQLAlchemy主要分成两部分:SQLAlchemy Core(SQLAlchemy核心)以及SQLAlchemy ORM(SQLAlchemy对象映射器)。SQLAlchemy Core包括SQL语言表达式、数据引擎、数据连接池等,所有一切的实现,都是为了连接不同类型的后台数据库,提交查询和更新SQL请求后台去执行、定义数据库数据类型和定义Schema为目的。SQLAlchemy ORM提供数据映射模式,就是把程序语言的对象数据映射成数据库中的关系数据,或者把关系数据映射成对象数据。SQLAlchemy架构图如下所示


SQLAlchemy架构

对象关系映射在Web应用程序框架中也经常提到,因为他是快速开发栈中的关键组件。现代程序开发主要大多是面向对象的,并且主流的数据库也是关系型数据库。所以,对象关系映射器映射器主要解决的就是将面向对象型的程序操作映射成对数据库进行操作,并且把数据库的查询结果转换成对象型数据,便于程序访问。下面简单给出一个例子,数据库中有两张表如下所示。

id name fullname password
1 ed Ed Jones f87ccs
2 wendy Wendy Williams fdsgdfg
3 mary Mary Contrary xvlo78
4 fred Fred Flinstone fsd133

表1 Table users

id user_id email_address
1 1 jones@google.com
2 1 25@yahoo.com
3 2 wendy@gmail.com

表2 Table addresses
从关系模型来看,数据库中有两张表,一张表users对应的是用户信息,包括用户id、名称、全名和密码;另一张表addresses存储的是用户的电子邮箱地址信息。两张表通过用户id关联起来:users表中,id是它的主键,在addresses表中,user_id是它的外键。已知一个用户,通过user_id可以在addresses表中查到该用户的所有电子邮箱信息。另一方面,已知一个电子邮箱,通过user_id可以在users表中查找到这是谁的电子邮箱。下面两个create sql语句建立上面两张表users和addresses,这是典型的关系型数据库sql语句。

CREATE TABLE USERS (
            id  INTERGER NOT NULL,
            name VARCHAR,
            fullname VARCHAR,
            password VARCHAR,
            PRIMARY KEY(id)
);
CREATE TABLE address (
            id INTERGER NOT NULL,
            email_address VARCHAR NOT NULL,
            user_id INTERGER,
            PRIMARY_KEY(id),
            FOREIGN KEY(user_id) REFERENCE users (id)
);

从对象模型来看,则是另一个世界。同样是上面的例子,对象关系映射器可以把上面两张表映射成两个类class User和class Address,它们的定义分别是:

>>> from sqlalchemy.ext.declarative import declarative_base
>>> from sqlalchemy import Column, Integer, String, ForeignKey
>>> from sqlalchemy.orm import relationship

>>> Base = declarative_base()
>>> class User():
...       __table__ = 'users'
...       id = Column(Integer,primary_key = True)
...       name = Column(String)
...       fullname = Column(String)
...       password = Column(String)
>>> class Address(Base):
...     __tablename__ = 'addresses'
...     id = Column(Integer, primary_key=True)
...     email = Column(String)
...     user_id = Column(Integer, ForeignKey('user.id'))
...     user = relationship('User', backref = backref('addresses', order_by = id))

粗略来说,一行记录成为了一个类,一列成为了一个类的属性。经过这样的模型转换和映射,我们就可以利用python这样的面向对象的语言通过SQLAlchemy生成SQL语句来查询和更新数据库记录。我们可以简单进行操作。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# 根据环境配置建立相应的数据库引擎
engine = create_engine()
Session = sessionmaker(bind=engine)
# 通过工厂模式建立数据库session
session = Session()
...
for u, a in session.query(User, Addresses). \
    filter(User.id == Addresses.user_id).\
        filter(Address.email_address=='jones@google.com').all():
    print(u,a)

这时候程序运行时,SQLAlchemy会产生对应的SELECT SQL查询语句提交给后台数据库去查询。后台生成的SQL查询语句如下所示。

SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password, addresses.id AS addresses_id, addresses.email_addresses AS addresses_email_addresses, addresses.user_id AS addresses_user_id
FROM users, addresses
WHERE users.id = addresses.user_id 
AND addresses.email_address = ?('jones@google.com',)

打印出来的结果是

<User('ed', 'Ed Jones', 'f8s7ccs')> <Address('jones@google.com')>

查询结果就是累User和类Addresses的某个实例,而要访问该实例的类属性,接下来就可以直接使用u.idu.nameu.email_address等面向对象程序化语句。这样,就相当于完成了查询结果从关系型数据库模型到对象型数据库的映射。至于使用SQLAlchemy完成其他操作,比如插入、更新和删除,也是类似的,下面是一个插入的例子。

ed_user = User('yaed', 'Ed Jones', 'f8s7ccs')
session.add(ed_user)
session.flush()

此时SQLAlchemy会提交一个INSERT SQL语句给后台数据库,如下所示。而数据库users表中就会多一条记录。

INSERT INTO users (name, fullname, password) VALUES (?, ?, ?)
('yead', 'Ed Jones', 'edspassword')

SQLAlchemy基本上支持绝大多数数据库SQL操作和特有属性,就拿上面的查询而言,由于表和表之间、类和类之间已经建立并且确定了键和外键的关系,SQLAlchemy可以直接利用join()函数来完成连接查询操作,而无需像上面例子那样再次把查询条件一一列出,至于join操作是主动还是被动的,SQLAlchemy也有一套参数可以提供开发者用程序进行选择、配置和控制。
另外,大多数数据库中的一些高级功能,比如事务处理等,SQLAlchemy也提供了相应的支持。也就是说,开发人员可以利用session的commit()和rollback()函数告诉后台数据库,对刚才的数据库改动分别作提交或者回退操作。
可以这么认为,SQLAlchemy是一座架设在Python和各种后台数据库的桥梁,让开发人员很容易并且简单的使用Python语句查询和更新数据库中的数据,而无须了解更多SQL语句的细节。更重要的是,如果后台数据库发生变化,假如数据从某类型的数据库管理系统迁移到另一种类型的数据库管理系统,开发人员的Python程序可以不用修改或者做少量配置文件的修改仍然可以正常运行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容