python学习-关系数据库

本文介绍了Python如何访问和操作关系型数据库,包括SQL、DB-API、SQLite、MySQL、PostgreSQL和SQLAlchemy。通过示例展示了如何创建数据库、表单,插入、查询数据,以及使用SQLAlchemy的SQL表达式语言和对象关系映射(ORM)。

关系型数据库

数据库服务器(database server),数据库(database)和数据(data)

SQL

SQL是一种声明式语言,是关系型数据库的通用语言。

SQL语句主要有两种类型:

DDL(数据定义语言):处理用户、数据库以及表单的创建、删除、约束和权限等。

DML(数据操作语言):处理数据插入、选择、更新和删除。

DB-API

应用程序编程接口(API)是访问某些服务的函数集合。DB-API(http://legacy.python.org/dev/peps/pep-0249/)是Python中访问关系型数据库的标准API。

它的主要函数如下:

.connect() 连接数据库,包含参数用户名、密码、服务器地址,等等。

cursor() 创建一个cursor对象来管理查询

execute()和executemany() 对数据库执行一个或多个SQL命令

fetchone()、fetchmany()、fetchall() 得到execute之后的结果。

SQLite

SQLite(http://www.sqlite.org)是一种轻量级、优秀的开源关系型数据库。它用Python的标准库实现,并存储数据再普通的文件中。这些文件在不同机器和操作系统之间是可移植的。该数据库仅支持原生SQL以及多用户并发操作。浏览器、智能手机和其他应用会把SQLite作为嵌入数据库。

首先使用connect()函数连接本地的SQLite数据库文件,这个文件和目录型数据库是等价的。 字符串’:memory:’仅用于在内存中创建数据库,有助于方便快速地测试。 下一个例子会创建一个数据库enterprise.db和表单zoo用于管理宠物动物园业务。

表单的列如下:

. critter 可变长度的字符串,作为主键。 . count 某动物的总数的整数值。 . damages 人和动物的互动中损失的美元数目。

创建数据库 enterprise.db

>>> import sqlite3
>>> conn = sqlite3.connect('enterprise.db')
>>> curs = conn.cursor()
>

创建表单zoo

>>> curs.execute('''CREATE TABLE zoo
    (critter VARCHAR(20) PRIMARY KEY,
     count INT,
     damages FLOAT)''')
<sqlite3.Cursor object at 0x01EDA720>

插入数据的方法一

>>> curs.execute('INSERT INTO zoo VALUES("duck",5,0.0)')
<sqlite3.Cursor object at 0x01EDA720>
>>> curs.execute('INSERT INTO zoo VALUES("bear",2,1000.0)')
<sqlite3.Cursor object at 0x01EDA720>

更安全的placeholder插入数据方法二

>>> ins = 'INSERT INTO zoo (critter,count,damages) VALUES(?,?,?)'
>>> curs.execute(ins,('weasel',1,2000.0))
<sqlite3.Cursor object at 0x01EDA720>
>>> curs.execute(ins,('weasel',1,2000.0))
<sqlite3.Cursor object at 0x01EDA720>

查询表单zoo

>>> curs.execute('SELECT * FROM zoo')
<sqlite3.Cursor object at 0x01EDA720>
>>> rows = curs.fetchall()
>>> print(rows)
[('duck', 5, 0.0), ('bear', 2, 1000.0), ('weasel', 1, 2000.0)]

按照count排序

>>> curs.execute('SELECT * FROM zoo ORDER BY count')
<sqlite3.Cursor object at 0x01EDA720>
>>> curs.fetchall()
[('weasel', 1, 2000.0), ('bear', 2, 1000.0), ('duck', 5, 0.0)]

哪个动物花费最多?

>>> curs.execute('''SELECT * FROM zoo WHERE damages = (SELECT MAX(damages) FROM zoo)''')
<sqlite3.Cursor object at 0x01EDA720
>>> curs.fetchall()
[('weasel', 1, 2000.0)]

已经打开的一个连接(connection)或者游标(cursor),不需要时应该关闭:

>>> curs.close()
>>> conn.close()

MySQL

MySQL(http://www.mysql.com)是一款开源关系型数据库,不同于SQLite,它是真正的数据库服务器。MysqlDB(http://sourceforge.net/projects/mysql-python)是最常用的MySQL驱动程序,但至今没有支持Python3,Python连接MySQL的几个驱动程序如下:

名称 链接 Pypi包 导入 注意

MySQL http://dev.mysql.com/doc/connector-

mysql-connector- mysql.connector

Connector python/en/index.html python

PYMySQL https://github.com/petehunt/PyMySQL/

pymysql pymysql

oursql http://pythonhosted.org/oursql/

oursql oursql 需要SQL客户端的C依赖库

PostgreSQL

PostgreSQL(http://www.postgresql.org/)是一款功能全面的开源关系型数据库。下表列出了Python链接PostgreSQL的几个驱动程序:

名称 链接 Pypi包 导入 注意

psycopg2 http://initd.org/psycopg/

psycopg2 psycopg2 需要来自PostgreSQL客户端工具的pg_config

py-postgresql http://python.projects.pgfoundry.org

py-postgresql postgresql

SQLAlchemy

每一种数据库实现的是包含自己特征的SQL,用于消除各数据库SQL差异的Python库是SQLAlchemy(http://www.sqlalchemy.org),不是Python标准库,使用下面的命令安装它:

$ pip install sqlalchemy

初始化连接字符串如下:

dialect + diver :// user : password @ host : port / dbname

含义如下:

dialect : 数据库类型

dirver : 使用该数据库的特定驱动程序

user\password: 数据库认证字符串

host\port: 数据库服务器的位置

dbname: 初始连接到服务器中的数据库

如下列出了常见方言和对应的驱动程序

方言 驱动程序

sqlite pysqlite(可忽略)

mysql mysqlconnector

mysql pymysql

mysql oursql

postgresql psycopg2

posgresql pypostgresql

在如下层级使用SQLAlchemy:

. 底层负责处理数据库连接池、执行SQL命令以及返回结果,和DB-API相似;

. 再往上是SQL表达式语言,更像Python的SQL生成器;

. 较高级的是对象关系模型(ORM),使用SQL表达式语言,将应用程序代码和关系型数据结构结合起来。

1、引擎层

以内置SQLite为例,连接字符串忽略host、port、user和password。dbname表示存储SQLite数据库的文件,如果省去dbname,SQLite会在内存创建数据库。如果dbname以反斜线(/)开头,那么它是文件所在的绝对路径(Linux和OS X是反斜线,而在Windows是例如C:\的路径名),否则它是当前目录下的相对路径。

示例如下:

导入库函数

>>> import sqlalchemy as sa
>

连接到数据库,并在内存中存储它(参数字符串‘sqlite://:memory:’也是可行的):

>>> conn = sa.create_engine('sqlite://')

创建包含三列的数据库表单zoo:运行函数conn.execute()返回一个SQLAlchemy的对象ResultProxy.

>>> conn.execute('''CREATE TABLE zoo
     (critter VARCHAR(20) PRIMARY KEY,
      count INT,
      damages FLOAT)''')
<sqlalchemy.engine.result.ResultProxy object at 0x026F3510>

向空表中插入三组数据:

>>> ins = 'INSERT INTO zoo(critter,count,damages) VALUES (?,?,?)'
>>> conn.execute(ins,'duck',10,0.0)
<sqlalchemy.engine.result.ResultProxy object at 0x026F3A10>
>>> conn.execute(ins,'bear',2,1000.0)
<sqlalchemy.engine.result.ResultProxy object at 0x026F3B30>
>>> conn.execute(ins,'weasel',1,2000.0)
<sqlalchemy.engine.result.ResultProxy object at 0x026F3990>
>>>
>

在数据库中查询放入的所有数据

>>> rows = conn.execute('SELECT * FROM zoo')
>>> print(rows)
<sqlalchemy.engine.result.ResultProxy object at 0x026F3B70>

在SQLAlchemy中,rows不是一个列表,不能直接输出,但它可以像列表一样迭代,每次可以得到其中的一行

>>> for row in rows :
    print(row)

('duck', 10, 0.0)
('bear', 2, 1000.0)
('weasel', 1, 2000.0)
>>>
>

要了解SQLAlchemy的连接池,可参阅文档(http://docs.sqlalchemy.org/en/latest/coe/pooling.html)

2、SQL表达式语言

相比引擎层,它能处理更多SQL方言的差异,对于关系型数据库应用是一种方便的中间层解决方案。 如下例,创建和管理数据表zoo:

导入和连接库

>>> import sqlalchemy as sa
>>> conn = sa.create_engine('sqlite://')
>

定义表单zoo,用表达式语言代替SQL:

>>> zoo = sa.Table('zoo',meta,
           sa.Column('critter',sa.String,primary_key=True),
           sa.Column('count',sa.Integer),
           sa.Column('damages',sa.Float)
           )
>>> meta.create_all(conn)
>

Table()方法的调用结构和表单的结构一致,此表单包含三列,在Table()方法调用时括号内部也调用三次Column()。zoo是连接SQL数据库和Python数据结构的一个对象

使用表达式语言函数插入数据:

>>> conn.execute(zoo.insert(('bear',2,1000.0)))
<sqlalchemy.engine.result.ResultProxy object at 0x027262F0>
>>> conn.execute(zoo.insert(('weasel',1,2000.0)))
<sqlalchemy.engine.result.ResultProxy object at 0x02726390>
>>> conn.execute(zoo.insert(('duck',10,0)))
<sqlalchemy.engine.result.ResultProxy object at 0x02726210>
>>>

下面创建SELECT语句(zoo.select()会选择出zoo对象表单的所有项,和SELECT * FROM zoo在普通SQL做的相同):

>>> result = conn.execute(zoo.select())

得到结果

>>> result = conn.execute(zoo.select())
>>> rows = result.fetchall()
>>> print(rows)
[('bear', 2, 1000.0), ('weasel', 1, 2000.0), ('duck', 10, 0.0)]
>>>

3、对象关系映射

在SQLAlchemy的顶层,对象关系映射(ORM)使用SQL表达式语言,但尽量隐藏实际数据库的机制。自己定义类,ORM负责处理如何读写数据库的数据。最基本观点是:同样使用一个关系型数据库,但操作数据的方式仍然和Python保持接近。

示例:我们定义一个类zoo,把他挂接到ORM,使用zoo.db文件以便于验证ORM是否有效。

初始化导入:

>>> import sqlalchemy as sa
>>> from sqlalchemy.ext.declarative import declarative_base
>

连接数据库:

>>> conn = sa.create_engine('sqlite:///zoo.db')
>

进入SQLAlchemy的ORM,定义类zoo,并关联它的属性和表单的列:

>>> Base = declarative_base()
>>> class Zoo(Base):
    __tablename__='zoo'
    critter = sa.Column('critter',sa.String,primary_key=True)
    count = sa.Column('count',sa.Integer)
    damages = sa.Column('damages',sa.Float)
    def __init__(self,critter,count,damages):
        self.critter = critter
        self.count = count
        self.damages = damages
    def __repr__(self):
        return "<Zoo({},{},{})>".format(self.critter,self.count,self.damages)

创建数据库和表单:

>>> Base.metadata.create_all(conn)
>

通过创建Python对象插入数据,ORM内部会管理这些:

>>> first = Zoo('duck',10,0.0)
>>> second = Zoo('bear',2,1000.0)
>>> third = Zoo('weasel',1,2000.0)
>>> first
<Zoo(duck,10,0.0)>

利用ORM接触SQL,创建连接到数据库的会话(session):

>>> from sqlalchemy.orm import sessionmaker
>>> Session = sessionmaker(bind=conn)
>>> session = Session()
>

借助会话,把创建的三个对象写入数据库。add()函数增加一个对象,add_all()增加一个列表:

>>> session.add(first)
>>> session.add_all([second,third])

最后使整个过程完整

>>> session.commit()

在当前目录下,创建了文件zoo.db,可以使用命令行的SQLite3程序验证一下:

$ sqlite3 zoo.db

问题:在执行时报不是内部命令的错误,暂未解决。

SQLAlchemy的作者撰写了完整的教程(http://docs.sqlalchemy.org/en/rel08/orm/tutorial.html),阅读后决定哪一级最适合自己的需求:

. 普通DB-API

. SQLAlchemy 引擎层

. SQLAlchemy 表达式语言

. SQLAlchemy ORM

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值