欲直接下载代码文件,关注咱们的公众号哦!查看历史消息便可!python
本文介绍如何利用python来对MySQL数据库进行操做,本文将主要从如下几个方面展开介绍:mysql
1.数据库介绍sql
2.MySQL数据库安装和设置数据库
3.Python操做MySQLwindows
在Python3.X上安装MySQL驱动python3.x
建立数据库链接服务器
建立数据表网络
增、改、删、查数据结构
分组、聚合app
按批量读取和处理数据
4.小结
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,能直接经过条件快速查询到指定的数据。随着信息技术和市场的发展,数据管理再也不仅仅是存储和管理数据,而转变成用户所须要的各类数据管理的方式。
目前,数据库主要有两种形式,一种是非关系型数据库,另外一种是关系型数据库。目前,咱们用得很是普遍的一种数据库类型是关系型数据库,它能够分为如下几种:
Oracle:
付费产品,主要是银行在用(万一出错了有Oracle背锅)
DB2:
付费产品,IBM产品
SQL Sever:
付费产品,微软产品,windows专用
PostgreSQL:
免费产品,主要是高校学术上使用
MySQL:
大众,免费,开源
做为手无寸金的大学生,咱们应该用哪一种数据库呢?固然是MySQL。一方面是由于MySQL免费,另外一方面是由于普及率最高,出了错,能够很容易找到解决方法。并且,围绕MySQL有一大堆监控和运维的工具,安装和使用很方便。因此,本文接下来也会介绍如何用Python来操做MySQL。
STEP1:MySQL官方网站上下载最新的MySQL Installer 8.0.14版本,下载连接为:
STEP2:按照指示操做默认安装,在安装时,MySQL会要求咱们设置一个本地登录帐号,帐号名通常命为root,端口为3306,自定义一个password便可。
至此,咱们完成了MySQL中用户的新建和受权。
目前,关于Python操做数据库主要有如下几种方法:
MySQLdb是用于Python链接MySQL数据库的接口,它实现了Python数据库API规范V2.0,基于MySQL C API上创建的,目前只支持Python2.x。
PyMySQL是Python中用于链接MySQL服务器的一个库,它支持Python3.x,是一个纯Python写的MySQL客户端,它的目标是替代MySQLdb。PyMySQL在MIT许可下发布。
因为 MySQL 服务器以独立的进程运行,并经过网络对外服务,因此,须要支持 Python 的 MySQL 驱动来链接到 MySQL 服务器。
目前,有两个 MySQL 驱动:
mysql-connector-python:是 MySQL 官方的纯 Python 驱动
MySQL-python :是封装了 MySQL C驱动的 Python 驱动
是一种ORM(Object-Relational Mapping)框架,将关系数据库的表结构映射到对象上,隐藏了数据库操做背后的细节,简化了数据操做。
STEP1:因为MySQL官方提供了mysql-connector-python驱动。安装时,在Anaconda Prompt中输入:
conda install mysql-connector-python
STEP2:使用如下代码来测试mysql-connector是否安装成功:
import mysql.connector
若是没有产生错误,则代表安装成功。
这里链接的是我以前建立的blank这个user。若是数据库已经存在的话,咱们能够直接链接;若是数据库不存在,直接链接则会报错,这个时候咱们就须要建立一个数据库,建立数据库能够在MySQL Workbench中建立,也能够在python中使用"CREATE DATABASE"语句,在本实验中,咱们使用已经在MySQL workbench中已经建好的test_s这个数据库。
import mysql.connector #链接数据库 config = { 'user' : 'blank' #用户名 'password' : 'password' #本身设定的密码 'host' : '127.0.0.1' #ip地址,本地填127.0.0.1,也能够填localhost 'port' : '3306' #端口,本地的通常为3306 'database' : 'test_s' #数据库名字,这里选用test_s } con = mysq;.connector.connect(**config)
cursor():表示游标
execute():是执行语句
# 建立一个表 # buffered = True 不设的话,查询结果没有读完会报错 # raise errors.InternalError("Unread result found") mycursor = con.cursor(buffered = True) mycursor.execute("CREATE TABLE customers(id INT AUTO_INCREMENT PRIMARY KEY, \ name VARCHAR(255) , address VARCHAR(255), \ 7sex VARCHAR(225) , age INT(10) , sl INT(10))")
VARCHAR()表示的是数据类型,定义的是变长字符串;INT()表示整型
STEP4:可是,当咱们再次执行语句的时候,因为已经建立了"customers"这个表,因此再次执行会报错,这个时候就须要加一个判断,判断这个表是否已经存在于test_s这个数据库中
ProgrammingError: Table 'customers' alreadyy exists
STEP5:咱们能够用"SHOW TABLES"语句来查看数据表是否已经存在,若是存在就print"table already exists",若是不存在,就print"table does not exist"。
def tableExists(mycursor, name): stmt = "SHOW TABLES LIKE '" +name+ "'" mycursor.execute(stmt) return mycursor.fetchone() mycursor = con.cursor() if tableExists(mycursor , 'customers'): print("table already exists") else: print("table not exists")
import mysql.connector #链接数据库 config = { 'user' : 'blank', 'password' :'fuying123888', 'host' : '127.0.0.1', 'port':'3306', 'database' : 'test_s' } con = mysql.connector.connect(**config) # 检查一个表是否存在 def tableExists(mycursor, name): stmt = "SHOW TABLES LIKE '"+name+"'" mycursor.execute(stmt) return mycursor.fetchone() # 删除一个表(不管它是否已经存在) def dropTable(mycursor, name): stmt = "DROP TABLE IF EXISTS "+name mycursor.execute(stmt) # buffered=True 不设的话,查询结果没有读完会报错 # raise errors.InternalError("Unread result found") mycursor = con.cursor(buffered=True) # 删除临时表 tableName = 'customers' dropTable(mycursor, tableName) # 建立一个表 mycursor.execute("CREATE TABLE customers(id INT AUTO_INCREMENT PRIMARY KEY,\ name VARCHAR(255), address VARCHAR(255), \ sex VARCHAR(225), age INT(10), sl INT(10))")
在cutomers表中插入数据用的是"INSERT INTO"语句。
除了用一条条用execute( )插入以外,咱们还能够用executemany()的方式批量插入,也就是val中包含的是一个元组列表,包含咱们想要插入的数据。
须要注意的事是:若是数据表格有更新,那么必须用到commit()语句,不然在workbench是看不到插入的数据的。
# 往表里插入一些记录 sql="INSERT INTO customers(name,address,sex,age,sl) VALUES(%s, %s,%s,%s,%s)" val = ("John", "Highway 21","M",23,5000) mycursor.execute(sql, val) val = ("Jenny", "Highway 29","F",30,12500) mycursor.execute(sql, val) val=[("Tom","ABC 35","M",35,14000), ("Tom1","Highway 29","M",28,6700), ("Lily","Road 11","F",30,8000), ("Martin","Road 24","M",35,14000), ("Sally","Fast 56","M",32,15000)] mycursor.executemany(sql, val) con.commit()
执行以上代码后,回到workbench,,咱们能够看到最终的结果为:
在cutomers表中更改数据用的是"UPDATE"语句。例如,咱们将最后一条 “Sally”的名字改为“Tiny”:
# 将Sally改成Tiny sql="UPDATE customers SET name='Tiny' WHERE name ='Sally'" mycursor.execute(sql) con.commit()
执行代码,回到workbench咱们能够看到结果为:
关于删,咱们在上文提到了删除表格,用的是“DROP TABLE ”语句,“IF EXISTS”关键字是用于判断表是否存在,只有在存在的状况才删除当咱们要删除一条数据记录时候,用到的语句是“DELETE FROM”语句。例如:咱们想在customers这个表格当中,删除name为Tiny的这一条记录:
#删除名字为Tiny的记录 sql="DELETE FROM customers WHERE name='Tiny'" mycursor.execute(sql) con.commit()
执行代码,回到workbench咱们能够看到结果为:
普通查询数据用的是SELECT语句。例如:咱们想查询customers的全部信息,而且进行打印输出:
#查询这里面全部的人: sql="SELECT * FROM customers" mycursor.execute(sql) myresult = mycursor.fetchall() # fetchall() 获取全部记录 for x in myresult: print(x)
获得最终结果为:
值得注意的是:fetchall()表示的是得到全部记录;fetchone()表示只获取一条数据;fetchmany(size=3)表示获取三条记录;
为了获取指定条件下的查找结果,咱们可使用where语句。例如:咱们想在查询customers的全部信息基础上,输出年龄大于30岁的消费者的信息:
sql="SELECT * FROM customers WHERE age > 30" mycursor.execute(sql) myresult = mycursor.fetchall() # fetchall() 获取全部记录 for x in myresult: print(x)
最终获得的结果为:
有时候为了进行模糊查询,能够匹配通配符,经过“LIKE”来进行查找:
百分号 (%):表明零个、一个或多个数字或字符;
下划线 (_):表明一个单一的数字或字符。
例如:查出全部名字中含有t的记录:
#%表明零个、一个或者多个数字或字符 #_表明一个单一的数字或者字符 sql = "SELECT * FROM customers WHERE name LIKE '%t%'" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
执行代码,咱们获得的结果以下:
值得注意的是:可是使用Like查询时,即便咱们在代码输入的是“t”,执行过程当中也会将含有“T”的记录一样输出,即用LIKE匹配通配符对大小写不敏感。为了区分大小写,能够用“GLOB”进行查询。
查询结果排序可使用 ORDER BY 语句,默认的排序方式为升序,若是要设置降序排序,能够设置关键字 DESC。例如:咱们要按照年龄对customers进行升序排列:
#排序 #按照年龄排序 sql = "SELECT * FROM customers ORDER BY age" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
执行代码,获得的结果为:
n zxx m nb
当数据库数量很是大的时候,为了限制查询的数据量,能够采用"LIMIT"语句来指定,好比咱们但愿在customers表中找出工资最高的三我的:
#找出其中工资最高的3我的 sql = "SELECT * FROM customers ORDER BY sl DESC LIMIT 3" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
执行代码,获得结果为:
有时候咱们在进行一次筛选后,还须要设定一个筛选条件进行二次筛选,咱们就能够采用“HAVING”语句。例如:咱们但愿统计在年龄处于20-30(不包括20岁,可是包括30岁)的人当中,选择薪资大于5000的消费者:
#二次过滤 #统计在年龄处于20-30之间的人中,选择薪资大于5000的人 sql = "SELECT * FROM customers WHERE age>20 and age<=30 HAVING sl>5000 " mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x) con.commit() con.close()
执行代码后,获得的结果以下:
在数据库中,分组经常使用的语句为“GROUP BY”语句,聚合函数,一般是配合分组进行使用,在数据库中经常使用的聚合函数为:
COUNT(*):表示计算总行数,括号能够写*和字段名字
MAX(column):表示求此列的最大值
MIN(column):表示求此列的最小值
SUM(column):表示求此列的和
AVG(column):表示求此列的平均值
以sex为类别进行GROUP BY 分组,加上WHERE来作条件判断。
#统计出男女的薪水总数 sql = "SELECT sex,sum(sl) FROM customers GROUP BY sex" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
最终结果为:
# 按照性别进行分组,统计出年龄在20-30岁的消费者的薪资 sql = "SELECT sex,sum(sl) FROM customers WHERE age>20 and age<=30 GROUP BY sex ORDER BY sl" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
值得注意的是:本例是以sex为类别进行GROUP BY 分组,加上WHERE来作条件判断,加上ORDER BY 排序,可是GROUP BY 的位置必需要在WHERE 以后,在ORDER BY 以前。
程序运行的时候,数据都是在内存中的,可是有时候若是数据量太大,内存会装不下,这个时候咱们就须要分批从数据库去读取数据,而后再处理,等处处理完了以后,再去读取。好比:咱们要从customers当中分批读取和处理薪资大于8000的消费者,并将其存入另外一张表中。咱们的作法是先新建一个表,而后从数据库当中读取3个,而且将读取的这3个进行处理,处理完读取的这三个后,再去数据库从新读取三个,直到数据库的数据读完为止。
# 分批读取而且处理将薪资大于8000的消费者的记录存到另外一张表中 # 建立一个临时表 tmpName = 'cust_tmp' dropTable(mycursor, tmpName) mycursor.execute("CREATE TABLE cust_tmp(id INT AUTO_INCREMENT PRIMARY KEY,\ name VARCHAR(255), address VARCHAR(255), \ sex VARCHAR(225), age INT(10), sl INT(10))") ins = con.cursor(buffered=True) if tableExists(mycursor, tableName): print("process table: %s", tableName) # 查询表里的记录 sql = "SELECT * FROM customers WHERE address is not null" mycursor.execute(sql) # 每次处理 batchsize 条记录,直到全部查询结果处理完 batchsize = 3 readsize = batchsize while readsize == batchsize: print("before batch") myresult = mycursor.fetchmany(size=batchsize) for x in myresult: if x[5]>8000: ins.execute("INSERT INTO"+tmpName+"(id,name,address,sex,age,sl) VALUES (%s, %s,%s, %s,%s,%s)", x) print(x) readsize = len(myresult) else: print("table: does not exists", tableName) con.commit() con.close()
咱们回到workbench找到这个新建的表格cust_tmp,咱们能够发现薪资大于8000的消费者都被记录上了:
执行代码,咱们能够看处处理的过程以下:
在第一批读取的三条记录中,只有两条是知足薪资大于8000的要求,第二批读取的三条记录中,只有一条知足薪资大于8000的要求,而在第三批读取的三条记录中,没有任何记录是知足薪资大于8000的要求,当没有记录能够读的时候,程序即中止。
值得注意的是:就分批读取的batchsize而言,当batchsize太大时,会致使内存装不下,batchsize过小,会致使每次经过网络链接数据库会很慢。所以,咱们选取batchsize大小的原则是在内存够用的前提下尽量的大,在真实的业务场景下,建议每次读取100以上,当内存够用的话,也能够增长至几千上万条。
本文介绍了Python+MySQL的基本操做,包括如何安装Mysql,如何装驱动,如何建立链接以及对数据库进行增删改查、分组聚合以及批量读取和处理等操做。可是,本文涉及到的只是对单表进行操做,只是数据库操做的冰山一角;在实际的开发和工做环境中,须要根据实际内容对多表进行操做,这部分请持续关注数据魔术师关于数据库的后期推文。