18--Python 数据库操作

2019-06-28  本文已影响0人  Roger田翔
@Author : Roger TX (425144880@qq.com)
@Link : https://github.com/paotong999

一、Python数据库API

Python 需要为操作不同的数据库使用不同的模块,但基本都遵守 Python 制订的 DB API 协议,目前该协议的最新版本是 2.0。
使用 Python DB API 2.0 操作数据库的基本流程如下

使用 Python DB API 2.0 操作数据库的基本流程如图

Python DB API 2.0 操作数据库的基本流程

数据库 API 的核心类
遵守 DB API 2.0 协议的数据库模块通常会提供一个 connect() 函数,该函数用于连接数据库,并返回数据库连接对象。数据库连接对象通常会具有如下方法和属性:

游标对象通常会具有如下方法和属性:

二、Python操作数据库SQLite

SQLite是一种嵌入式数据库,它的数据库就是一个文件。
Python内置了SQLite3,在Python中使用SQLite,不需要安装任何东西,直接使用。

# 导入访问SQLite的模块
import sqlite3
# ①、打开或创建数据库
# 也可以使用特殊名::memory:代表创建内存中的数据库
conn = sqlite3.connect('first.db')
# ②、获取游标
c = conn.cursor()
# ③、执行DDL语句创建数据表
c.execute('''create table user_tb(
    _id integer primary key autoincrement,
    name text,
    pass text,
    gender text)''')
# 执行DDL语句创建数据表
c.execute('''create table order_tb(
    _id integer primary key autoincrement,
    item_name text,
    item_price real,
    item_number real,
    user_id inteter,
    foreign key(user_id) references user_tb(_id) )''')
# 执行DML的insert语句插入数据
c.execute('insert into user_tb values(null, ?, ?, ?)',
    ('孙悟空', '123456', 'male'))
c.execute('insert into order_tb values(null, ?, ?, ?, ?)',
    ('鼠标', '34.2', '3', 1))
# SQLite 数据库 API 默认是开启了事务,需要提交事务
conn.commit()
# 调用executemany()方法把同一条SQL语句执行多次
c.executemany('insert into user_tb values(null, ?, ?, ?)',
    (('sun', '123456', 'male'),
    ('bai', '123456', 'female'),
    ('zhu', '123456', 'male'),
    ('niu', '123456', 'male'),
    ('tang', '123456', 'male')))
# 通过rowcount获取被修改的记录条数
print('修改的记录条数:', c.rowcount)
conn.commit()
# ④、关闭游标
c.close()
# ⑤、关闭连接
conn.close()
  1. 操作数据之后需要提交事务,否则对数据库的修改(包括插入数据、修改数据、删除数据)不会生效
  2. 调用 executemany() 方法执行一条 insert 语句,但调用该方法的第二个参数是一个元组,该元组的每个元素都代表执行该 insert 语句一次,在执行 insert 语句时这些元素负责为该语句中的“?”占位符赋值
  3. executemany() 也可以重复执行 update 语句或 delete 语句,只要其第二个参数是一个序列,序列的每个元素都可对被执行 SQL 语句的参数赋值即可
import sqlite3
conn = sqlite3.connect('first.db')
c = conn.cursor()

# 调用执行select语句查询数据
c.execute('select * from user_tb where _id > ?', (2,))
print('查询返回的记录数:', c.rowcount)
# 通过游标的description属性获取列信息
for col in (c.description):
    print(col[0], end='\t')
print('\n--------------------------------')
while True:
    # 获取一行记录,每行数据都是一个元组
    row = c.fetchone()
    # 如果抓取的row为None,退出循环
    if not row :
        break
    print(row)

c.close()
conn.close()
  1. 不能使用 executemany() 执行查询语句,executemany() 只支持DML语句
  2. 对于查询语句,rowcount返回的值为-1
  3. fetchone() 方法每次获取一条记录,也可以使用 fetchmany(n) 或 fetchall() 方法一次获取多条记录
while True:
    rows = c.fetchmany(3)
    # 如果抓取的rows为None,退出循环
    if not rows :
        break
    # 再次使用循环遍历获取的列表
    for r in rows:
        print(r)

三、Python操作数据库MySQL

安装MySQL驱动
由于MySQL服务器以独立的进程运行,并通过网络对外服务,所以需要支持Python的MySQL驱动来连接MySQL服务器。
MySQL官方提供了mysql-connector-python驱动,但是安装的时候需要给pip命令加上参数--allow-external:

$ pip install mysql-connector-python --allow-external mysql-connector-python

如果上面的命令安装失败,可以试试另一个驱动:

$ pip install mysql-connector

我们演示如何连接到MySQL服务器的test数据库:

# 导入访问MySQL的模块
import mysql.connector
# ①、连接数据库
conn = conn = mysql.connector.connect(user='root', password='123456',
    host='localhost', port='3306',
    database='python', use_unicode=True)
# ②、获取游标
c = conn.cursor()
# ③、执行DDL语句创建数据表
c.execute('''create table user_tb(
    user_id int primary key auto_increment,
    name varchar(255),
    pass varchar(255),
    gender varchar(255))''')
# 执行DDL语句创建数据表
c.execute('''create table order_tb(
    order_id integer primary key auto_increment,
    item_name varchar(255),
    item_price double,
    item_number double,
    user_id int,
    foreign key(user_id) references user_tb(user_id) )''')
# 执行DML的insert语句插入数据
c.execute('insert into user_tb values(null, %s, %s, %s)'%
    ('孙悟空', '123456', 'male'))
c.execute('insert into order_tb values(null, %s, %s, %s, %s)'%
    ('鼠标', '34.2', '3', 1))
# 调用executemany()方法把同一条SQL语句执行多次
c.executemany('insert into user_tb values(null, %s, %s, %s)'%
    (('sun', '123456', 'male'),
    ('bai', '123456', 'female'),
    ('zhu', '123456', 'male'),
    ('niu', '123456', 'male'),
    ('tang', '123456', 'male')))
# 关闭事务支持conn.autocommit = True
conn.commit()
# ④、关闭游标
c.close()
# ⑤、关闭连接
conn.close()
  1. 与连接 SQLite 相比,最大的区别在于第 5 行代码,程序要连接 localhost 主机上 3306 端口服务的 python 数据库。
  2. 与连接 SQLite 相比,MySQL 语句中的占位符:%s
  3. MySQL 数据库模块的连接对象有一个 autoconunit 属性,如果将该属性设为 True,则意味着关闭该连接的事务支持,程序每次执行 DML 语句之后都会自动提交,这样程序就无须调用连接对象的 commit() 方法来提交事务了

MySQL callproc方法:调用数据库存储过程
MySQL 数据库模块为游标对象提供了一个非标准的 callproc(self, procname, args=()) 方法,该方法用于调用数据库存储过程。

callproc 方法的 procname 参数代表存储过程的名字,而 args 参数则用于为存储过程传入参数。

存储过程

delimiter //
create procedure add pro(a int, b int, out sum int)
begin
set sum = a + b;
end;
//

MySQL 数据库模块来调用存储过程

# 导入访问MySQL的模块
import mysql.connector
# ①、连接数据库
conn = conn = mysql.connector.connect(user='root', password='32147',
    host='localhost', port='3306',
    database='python', use_unicode=True)
# ②、获取游标
c = conn.cursor()
# ③、调用callproc()方法执行存储过程
# 虽然add_pro存储过程需要3个参数,但最后一个参数是传出参数,
# 因此程序不会用它的值
result_args = c.callproc('add_pro', (5, 6, 0))
# 返回的result_args既包含了传入参数的值,也包含了传出参数的值
print(result_args)
# 如果只想访问传出参数的值,可直接访问result_args的第3个元素,如下代码
print(result_args[2])
# ④、关闭游标
c.close()
# ⑤、关闭连接
conn.close()

运行上面的程序,可以看到如下输出结果:

(5, 6, 11)
11

四、ORM框架SQLAlchemy

首先通过pip安装SQLAlchemy:

pip install sqlalchemy

第一步,导入SQLAlchemy,并初始化DBSession:

# 导入:
from sqlalchemy import Column, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# 创建对象的基类:
Base = declarative_base()

# 定义User对象:
class User(Base):
    # 表的名字:
    __tablename__ = 'user'

    # 表的结构:
    id = Column(String(20), primary_key=True)
    name = Column(String(20))
    # 一对多:
    books = relationship('Book')

class Book(Base):
    __tablename__ = 'book'

    id = Column(String(20), primary_key=True)
    name = Column(String(20))
    # “多”的一方的book表是通过外键关联到user表的:
    user_id = Column(String(20), ForeignKey('user.id'))

# 初始化数据库连接:
engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test')
# 创建DBSession类型:
DBSession = sessionmaker(bind=engine)

create_engine()用来初始化数据库连接:

'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'

第二步,向数据库表中添加一行记录:

# 创建session对象:
session = DBSession()
# 创建新User对象:
new_user = User(id='5', name='Bob')
# 添加到session:
session.add(new_user)
# 提交即保存到数据库:
session.commit()
# 关闭session:
session.close()

第三步,从数据库表中查询数据:

# 创建Session:
session = DBSession()
# 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行:
user = session.query(User).filter(User.id=='5').one()
# 打印类型和对象的name属性:
print('type:', type(user))
print('name:', user.name)
# 关闭Session:
session.close()
上一篇 下一篇

猜你喜欢

热点阅读