sqlalchemy:SQLAlchemy指南

  这个入门指导用于SQLAlchemy快速入门并便利SQLAlchemy简单功能如果你可以跳过这部分进入 主文档 会涉及更多内容如下例子全部是在Python交互模式下完成了并且全部通过了 doctest 测试

  1 安装1.1 安装SQLAlchemy  从 uptools 安装是非常简单只要运行如下命令即可:

# easy_ SQLAlchemy  这将会在Python Cheese Shop获取SQLAlchemy最新版本并安装或者你也可以使用up.py安装个发行包:

# python up.py 1.2 安装个数据库API  SQLAlchemy被设计用于操作个 DBAPI 实现包括大多数常见数据库如果你有个支持DBAPI实现那么可以跳入下另外SQLite是个易于使用数据库可以快速开始并且他可以使用内存数据库如果要使用SQLite你将会需要:

  pysqlite - SQLitePython接口

  SQLite

  注意在Windows下并不需要SQLiteWindows版pysqlite已经内含了pysqlite和SQLite可以被安装到Linux或FreeBSD通过预编译或从源码安装

  预编译包地址为:

  http://initd.org/tracker/pysqlite/wiki/PysqlitePackages

  2 快速开始2.1 导入  SQLAlchemy提供了完整命名空间只要导入sqlalchemy即可无需其子包为了方便使用本教程我们导入所有命名到本地命名空间:

>>> from sqlalchemy import *2.2 连接到数据库  导入的后步是连接到需要数据库表现为(represent)为个Engine对象这个对象处理了连接管理和特定数据库操作下面我们连接SQLite基于文件数据库”tutorial.db”

>>> db=create_engine("sqlite:///tutorial.db")  创建数据库引擎更多信息查看”Database Engines”

  3 SQLAlchemy是两个库包装  现在已经完成了安装和连接数据库可以开始做点实际事情了但首先需要有些解释

  SQLAlchemy核心有两个完全区别功能个在另个的上工作个是 SQL语言构造器 个是 ORM SQL语言构造器允许 ClauseElements 来构造SQL表达式这些 ClauseElements 可以在编译成串并绑定到数据库后用于执行并返回个叫做 ResultProxy 对象类似于个结果集对象但是更象dbapi高版本 cursor 对象

  ORM是建立在SQL语言构造器的上工具集用于将Python对象映射到数据库提供了系列接口用于从数据库中存取对象(行)在ORM工作时在底层SQL语言构造器API这些通用操作有些许区别区别你不再使用行而是使用自定义类对象来操作另外数据库查询方式也区别ORM可以生成大多数SQL查询除此的外还可以在类中定义更多操作

  SA功能强大无和伦比只是有两个混合在思路方法有些复杂有效使用SA思路方法是先了解这两种区别工具集这是两个区别概念而大家常常混交SQL语言构造器和ORM关键区别是使用cursor形式结果集时使用是SQL语言构造器;而使用类例子进行管理时使用是ORM

  本指南首先介绍SQL语言构造器首先需要声明数据库信息叫做 table metadata 本指南包含了些SQL构造例子包括如何有效使用SQL语言构造器例子

  4 操作数据库对象  在SQLAlchemy核心哲学中表格和类是区别如此SQLAlchemy提供了构造表格思路方法(使用表格元信息table metadata)所以我们从构造表格元信息对象和定制操作他们对象开始稍后我们可以看到SQLAlchemyORM提供了表格元信息高层封装允许我们随心所欲装载和保存Python类

  4.1 定义元信息绑定到引擎  首先表格必须已经在MetaData集合中我们将要创建简单(handy)表格MetaData并自动连接到引擎(将个模式(schema)对象连接到引擎成为绑定binding):

>>> metadata=BoundMetaData(db)  个构造BoundMetaData对象等同思路方法是直接使用引擎URL这将会帮我们 create_engine

>>> metadata=BoundMetaData("sqlite:///tutorial.db")  现在我们告知metadata有关数据库中表格我们可以使用(issue)CREATE语句来创建表格并且通过他们来创建和执行SQL语句除非需要打开和关闭任何连接这都是自动完成注意这个功能是推荐使用SQLAlchemy包含了使用模式进行连接管理和SQL构造全部功能并可以在任何引擎上进行操作

  本教程是教会大家使用”bound”对象他可以使得代码简单和易读

  4.2 创建表格  使用metadata作为基本连接我们可以创建表格:

>>> users_table=Table('user',metadata,
...   Column('user_id',Integer,primary_key=True),
...   Column('user_name',String(40)),
...   Column('password',String(10))
... )
  有如你看到我们刚刚定义了个叫做users表格并拥有3个列:user_id作为主键user_name和password它现在只是个对象而和数据库中表格没有必然联系为了让表格生效我们使用create思路方法有趣我们可以让SQLAlchemy发送SQL语句到数据库时同时显示SQL语句只要设置BoundMetaData关联Engineecho选项即可:

>>> metadata.engine.echo=True
>>> users_table.create
CREATE TABLE users (
  user_id INTEGER NOT NULL,
  user_name VARCHAR(40),
  password VARCHAR(10),
  PRIMARY KEY (user_id)
)
...
  或者如果users表格已经存在了(比如你第 2次运行这些例子)在这种情况下你可以跳过create思路方法你设置可以跳过列定义而是让SQLAlchemy自动从数据库装入定义:

>>> users_table=Table('users',metadata,autoload=True)
>>> list(users_table.columns)[0].name
'user_id'
  有关表格元信息文档在”Database Meda Data”中

  4.3 插入记录  插入记录是通过表格对象insert思路方法实现这将会定义个子句对象(clause object)(就是CluseElement)来代理INSERT语句:

>>> i=users_table.insert
>>> i
<sqlalchemy.sql._Insert object at 0x...>
>>> pr i
INSERT INTO users (user_id,user_name,password) VALUES (?,?,?)
  当我们创建这个插入语句对象时语句本身也绑定到了Engine并已经可以执行了子句对象execute思路方法将会将对象编译为特定引擎SQL方言并且执行语句:

>>> i.execute(user_name='Mary',password='secure')
INSERT INTO users (user_name,password) VALUES (?,?)
['Mary','secure']
COMMIT
<sqlalchemy.engine.base.ResultProxy object at 0x...>
>>> i.execute({'user_name':'Tom'},{'user_name':'Fred'},{'user_name':'Harry'})
INSERT INTO users (user_name) VALUES (?)
[['Tom'],['Fred'],['Harry']]
COMMIT
<sqlalchemy.engine.base.ResultProxy object at 0x...>
  注意VALUES子句会自动调整参数数量这是ClauseElement编译步骤并不依赖于特定数据库执行参数也是如此

  当构造子句对象时SQLAlchemy会绑定所有值到参数在构造时参数绑定总是依靠键值对在编译时SQLAlchemy会转换他们到适当格式基于DBAPI参数风格这在DBAPI中描述参数位置绑定中同样工作很好

  这些文档继承于”Inserts”

  4.4 查询  我们可以检查users表中已经存在数据思路方法同插入例子只是你需要表格select思路方法:

>>> s=users_table.select
>>> pr s
SELECT users.user_id,users.user_name,users.password
FROM users
>>> r=s.execute
SELECT users.user_id,users.user_name,users.password
FROM users
  这时我们并没有忽略execute返回值他是个ResultProxy例子保存了结果而行为非常类似于DBAPI中cursor对象:

>>> r
<sqlalchemy.engine.base.ResultProxy object at 0x...>
>>> r.fetchone
(1,u'Mary',u'secure')
>>> r.fetchall
[(2,u'Tom',None),(3,u'Fred',None),(4,u'Harry',None)]
  查询条件同Python表达式使用Column对象所有表达式中Column对象都是ClauseElements例子例如Select、Insert和Table对象本身:

>>> r=users_table.select(users_table.c.user_name'Harry').execute
SELECT users.user_id,users.user_name,users.password
FROM users
WHERE users.user_name=?
['Harry']
>>> row=r.fetchone
>>> pr row
(4,u'Harry',None)
  所幸是所有标准SQL操作都可以用Python表达式来构造包括连接(join)、排序(order)、分组(group)、(function)、子查询(correlated subquery)、联合(union)等等有关查询文档”Simple Select”

  4.5 操作记录  你可以看到当我们打印记录时返回可执行对象它以元组打印记录这些记录实际上同时支持列表(list)和字典(dict)接口字典接口允许通过列名定位字段或者通过Column对象:

>>> row.keys
['user_id','user_name','password']
>>> row['user_id'],row[1],row[users_table.c.password]
(4,u'Harry',None)
  通过Column对象来定位是很方便这样避免了使用列名方式

  结果集也是支持序列操作但是相对于select还有微小差别就是允许指定所选列:

>>> for row in select([user_table.c.user_id,users_table.c.user_name]).execute:
...   pr row
SELECT users.user_id,users.user_name
FROM users

(1,u'Mary')
... ...
4.6 表间关系  我们可以创建第 2个表格email_addresses这会引用users表定义表间关联使用ForeignKey构造我们将来也会考虑使用表格CREATE语句:

>>> email_addresses_table=Table('email_addresses',metadata,
...   Column('address_id',Integer,primary_key=True),
...   Column('email_address',String(100),nullable=False),
...   Column('user_id',Integer,ForeignKey('users.user_id')))
>>> email_addresses_table.create
CREATE TABLE email_addresses (
  address_id INTEGER NOT NULL,
  email_address VARCHAR(100) NOT NULL,
  user_id INTEGER,
  PRIMARY KEY (address_id),
  FOREIGN KEY(user_id) REFERENCES users (user_id)
)
...
  上面email_addresses表和表users通过ForeignKey(’users.user_id’)相联系ForeignKey构造器需要个Column对象串代表表明和列名当使用了串参数时引用表必须已经存在于相同MetaData对象中当然可以是另外个表

  下面可以尝试插入数据:

>>> email_addresses_table.insert.execute(
...   {'email_address':'[email protected]','user_id':2},
...   {'email_address':'[email protected]','user_id':1})
INSERT INTO email_addresses (email_address,user_id) VALUES (?,?)
[['[email protected]',2],['[email protected]',1]]
COMMIT
<sqlalchemy.engine.base.ResultProxy object at 0x...>
  在两个表的间我们可以使用 join 思路方法构造个连接:

>>> r=users_table.join(email_addresses_table).select.execute
SELECT users.user_id, users.user_name, users.password,
email_addresses.address_id, email_addresses.email_address,
email_addresses.user_id
FROM users JOIN email_addresses _disibledevent='Mary')
>>> mary is mary2
True
  在唯映射中会话可以确保安全操作对象

  如果两个区别会话同时操作个对象会检测到并发;SA会使用简单并发控制来保存对象可以选择使用拥有更强使用ids检查参考 Mapper Arguments 了解更多细节

Tags:  pythonsqlalchemy sqlalchemy

延伸阅读

最新评论

发表评论