前言
本文主要总结我实际使用python操作MySQL数据库用到的几种方法,希望能对你有所帮助。在学习后面实例代码前。首先对数据库需要有一定的了解,而且本地需要安装MySQL数据库,并设置好MySQL账户和密码。
数据库主要分为关系型和非关系型数据库。MySQL属于关系型数据库库。
PyMySQL模块
首先总结pymysql模块所常用到的一些方法,它主要用来操作MySQL数据库。如需查看官方文档,请点击这里。
安装
推荐使用pip方式安装,最新版本为0.9.2。本文方法基于此版本总结。
要求
python2版本要求2.7及以上,python3版本要求3.5及以上。
MySQL版本>=5.5,MariaDB版本>=5.5。
基础用法
我们对数据的操作基本可以概括为增、删、改、查这几个方面。所以pymysql用法也主要是以这4个方面为主。
下面的实例代码为使用pymysql库初始连接对象,定义游标和执行sql命令调用的相关方法。
注意:每次执行数据库操作时,最好先初始化数据库连接,同时数据库操作完毕之后,关闭连接。因为数据库连接如果长时间不操作的话,会自动终止连接。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import pymysql CONFIG = { 'host': 'localhost', 'port': 3306, 'user': 'root', 'passwd': '', 'db': 'test', 'charset': 'utf8', } def init_connect(**kargs): db=pymysql.connect(**kargs) cursor=db.cursor() return db,cursor
|
创建表
创建一个classes表
1 2 3 4 5 6 7 8 9
| sql="""CREATE TABLE classes ( id INT(10) NOT NULL AUTO_INCREMENT, name CHAR(20) NOT NULL, PRIMARY KEY(id) ) DEFAULT CHARSET=utf8""" try: cursor.execute(sql) except: print('create table failed')
|
创建一个students表
1 2 3 4 5 6 7 8 9 10 11 12 13
| sql="""CREATE TABLE students ( id INT(10) NOT NULL AUTO_INCREMENT, name CHAR(20) NOT NULL, age INT(4), gender CHAR(1), class_id INT(10), FOREIGN KEY(class_id) REFERENCES classes(id), PRIMARY KEY (id) ) DEFAULT CHARSET=utf8""" try: cursor.execute(sql) except: print('create table failed')
|
增
增,增加MySQL数据库中的数据表的记录,也就是添加数据。对应的SQL命令是INSERT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function=init_connect(**CONFIG) db=function[0] cursor=function[1] sql = """INSERT INTO STUDENTS(NAME, AGE, SEX, CLASS) VALUES ('%s', %s, '%s', '%s')" % ('xiaoming', 20, 'M', 'class1')""" try: cursor.execute(sql) db.commit() except: db.rollback()
db.close()
|
删
删,删除数据表中的记录,也就是删除数据。对应SQL命令是DELETE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function=init_connect(**CONFIG) db=function[0] cursor=function[1]
sql = "DELETE FROM STUDENTS WHERE AGE > %s" % (20) try: cursor.execute(sql) db.commit() except: db.rollback()
db.close()
|
改
改,修改数据表中的记录,也就是更新数据。对应的SQL命令是UPDATE
1 2 3 4 5 6 7 8 9 10 11 12 13
| function=init_connect(**CONFIG) db=function[0] cursor=function[1] sql="UPDATE students SET AGE = 19 WHERE NAME='xiaoming'" try: cursor.execute(sql) db.commit() except: db.rollback() db.close()
|
查
查,查询数据表中的记录。对应的SQL命令是SELECT。如果使用默认的cursorclass查询数据表记录,默认返回的数据类型为元祖类型。
- fetchall() 返回所有查询的所有记录
- fetchone() 返回单条记录
- rawcount() 返回执行execute()方法影响的命令行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
CONFIG = { 'host': '127.0.0.1', 'port': 3306, 'user': 'root', 'passwd': '', 'db': 'test', 'charset': 'utf8', 'cursorclass': pymysql.cursors.DictCursor } db=pymysql.connect(**CONFIG) cursor=db.cursor() sql="SELECT * FROM students WHERE CLASS="class1" try: # 执行sql命令 cursor.execute(sql) # 获取所有记录列表,字典类型的数据 results=cursor.fetchall() # 根据需要处理数据,这里只是打印 for i in results: print(i) except: print('Error')
|
SQLAlchemy模块
介绍
SQLAlchemy库是python中著名的ORM(Object Relationship Mapping)框架。在学习这个库之前,先要学习并理解什么是ORM框架。ORM全称对象关系映射,把关系型数据库的表结构映射到对象上。谁来做映射这个动作呢?没错,就是ORM框架,也就是本文中的SQLAlchemy模块。
简而言之,ORM就是把数据库表的行与相应的对象建立关联,互相转换。
该模块支持PostgreSQL | MySQL | SQLite | Oracle | Microsoft SQL Server等数据库,一般我们常用的是MySQL数据库。
原理
主要应用了metaclass元类这一强大的功能,对于我们来说基本上很难用上元类这个功能,所以以下这些理解即可。什么叫元类?我们知道实例对象根据定义的类生成,而类则可以根据元类生成。你也理解成类是根据metaclass创建的”实例对象”。如果你想自己写一个简单ORM框架,那么元类可以去深入学习。
安装
sqlalchemy版本为: 1.2.14。本文所有方法基于此版本总结。
用法
同样的SQLAlchemy用于操作数据库能够实现增、删、改、查等几个动作。它相比pymysql更加抽象,但也更加易用。常用于web应用的后端开发。
舒适化
1 2 3 4 5 6 7 8 9 10
| from sqlalchemy import Column, Integer, String, create_engine, ForeignKey from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base
Base=declarative_base()
engine=create_engine("mysql+mysqlconnector://root:@localhost:3306/test", encoding='utf-8', echo=True)
DBSession=sessionmaker(bind=engine)
|
表映射
首先我们需要在数据库test中创建两张表,以下使用sql语言创建了2张表,并插入了一些数据记录。这里解释一下主键,主键一般命名为id,它唯一标识了一条数据记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| CREATE DATABASE IF NOT EXISTS test;
USE test;
DROP TABLE phone IF EXISTS; DROP TABLE company IF EXISTS;
CREATE TABLE company ( id BIGINT NOT NULL AUTO_INCREMENT, name VARCHAR(20) NOT NULL, country VARCHAR(20) NOT NULL, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE phone ( id BIGINT NOT NULL AUTO_INCREMENT, name VARCHAR(20) NOT NULL, price BIGINT NOT NULL, company_name VARCHAR(20) NOT NULL, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
INSERT INTO company(id, name, country) VALUES (1, 'Apple', 'America'); INSERT INTO company(id, name, country) VALUES (2, 'Samsung', 'Korea'); INSERT INTO company(id, name, country) VALUES (3, 'Huawei', 'China'); INSERT INTO company(id, name, country) VALUES (4, 'Xiaomi', 'China'); INSERT INTO company(id, name, country) VALUES (5, 'Vivo', 'China');
INSERT INTO phone(id, name, price, company_name) VALUES (1, 'CC9', 1999, 'Xiaomi') INSERT INTO phone(id, name, price, company_name) VALUES (1, 'Xiaomi9', 2999, 'Xiaomi')
SELECT 'OK' AS 'Result:';
|
将数据库中的表映射成类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Company(Base): __tablename__ = 'company' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(20)) country = Column(String(20)) class Phone(Base): __tablename__='phone' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(20)) price = Column(Integer) company_name = Column(String(20))
|
外键
关系数据库的多个表可以用外键实现一对多、多对多等关联。但使用外键会降低数据库的查询性能。
例如,如果一个User拥有多个Book,就可以定义一对多关系如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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)) user_id = Column(String(20), ForeignKey('user.id'))
|
增
增,即添加数据。数据库表中添加一条记录,使用ORM框架后可以视为添加一个phone对象。
关键是获取session,然后把对象添加到session,最后提交并关闭。DBSession
对象可视为当前数据库连接。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| session=DBSession()
iphoneX=Phone(id=2, name='iPhone X', price=8388, company_name='Apple') P30Pro=Phone(id=3, name='P30 Pro', price=5488, company_name='Huawei') S10=Phone(name='Galaxy S10', price=5999, company_name='Samsung') Z5x=Phone(name='Vivo Z5x', price=1599, company_name='vivo') Neo=Phone(name='IQOO Neo', price=2499,company_name='vivo')
session.add(iphoneX)
session.add_all([P30Pro,S10,Z5x,Neo])
session.commit()
session.close()
|
删
删,即删除数据。在删除数据前,首先需要查找到该数据。例如:删除Phone表中,属于Vivo公司手机的数据。
1 2 3 4 5 6 7 8 9
| session=DBSession()
phone = session.query(Phone).filter_by(company_name='Vivo').all()
for i in phone_list: session.delete(i)
session.close()
|
改
改,即修改数据。同样的需要查找到该数据,然后再进行修改。
1 2 3 4 5 6 7 8 9 10 11 12
| session=DBSession()
sony=Company(name='suoni',country='Japan')
session.add(sony) session.commit()
company=session.query(Company).filter(name=='suoni').first() company.name='sony'
session.commit()
|
查
查,即查询数据。
查询数据过滤有两种方法,两者区别如下:
- filter_by() column=数据,过滤,使用起来比较方便
- filter() 稍微复杂,但能实现更多复杂的查询操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| phone1 = session.query(Phone).filter(Phone.id=='2').one() print('type:',type(phone)) print('Phone Name:', phone.name)
phone_list = session.query(Phone).filter(Phone.company_name == 'Apple').all() print('type',type(phone_list)) for i in phone_list: print('Apple品牌:', i.name)
phone2 = session.query(Phone).get(2) print(phone2.name)
phone_sql = session.query(Phone).filter(Phone.id=='1') print(phone_sql)
|
filter()过滤几种方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| phone_list1 = session.query(Phone).filter(Phone.name.like("%Phone%")).all()
phone_list2 = session.query(Phone).filter(Phone.company_name != 'Apple').all()
phone_list3 = session.query(Phone).filter(Phone.id.in_(['1', '2']))
phone_list4 = session.query(Phone).filter(~Phone.id.in_(['1', '2']))
from sqlalchemy import and_ phone_list5 = session.query(Phone).filter(and_(Phone.company_name=='Xiaomi', Phone.price==2999)).all() phone_list5 = session.query(Phone).filter(Phone.company_name=='Xiaomi', Phone.price==2999).all()
from sqlalchemy import or_ phone_list6 = session.query(Company).filter(or_(Company.country=='China', Company.country=='America')).all
|
计数方法:count()
1
| num = session.query(Phone).filter(Phone.name.like('%ed')).count()
|
总结
以上大致总结了一些比较常用的方法。如果你需要使用的方法,这里没有总结。可以去查看官方文档和其他博客文章。