一 安装基本环境

1 简介

MySQL 基于TCP 协议之上的开发,但是网络连接后,传输的数据必须遵循MySQL的协议,封装好MySQL协议的包,就是驱动程序

MySQL 的驱动

MySQLDB 最有名的库,对MySQL 的C Client 封装实现,支持python2,不更新了,不支持python3

MySQL 官方的connector

pymysql 语法兼容MySQLdb,使用python写的库,支持python3

2 安装MySQL数据库

本文使用的是mariadb数据库,与MySQL相似

1 挂载镜像文件(本次使用的是本地镜像文件)

2 启动MySQL数据库

3 创建用户名和密码并刷新

grant all(表示所有操作) on .(库.表(所有的,也可以指定)) to root@localhost(设置用户名为root,链接为本地链接) identified by 'roiot123';(设置密码)

flush privileges;(刷新权限)

4 修改默认字符集:

server.cnf 中的操作(前面必须有空格,否则不生效,不能写入汉字)

client.cnf 操作同上

重启加载字符集

5 查看字符集是否加载完毕

如上,则表示加载完毕!!!

6 创建数据库

二 MySQL-python

1 安装

1 安装

2 查看安装是否完成,若完成,则不会报错

2 连接一般流程

建立连接

获取游标

执行SQL

提交事务

释放资源

2 MySQL链接基本操作及说明

1 导入MySQLdb 模块

导入名重命名重命名

2 创建连接

参数含义如下

connection 初始化常用参数

说明

host

主机

user

用户名

password

密码

database

数据库

port

端口

其中必选参数是user和passwd 其他可选

其中user 表示数据库的用户名,就是上面初始化的用户名和密码,db 是上面初始化的数据库,host 表示本地链接,可以使用IP地址或域名进行远程链接,charset 表示链接使用的字符集,如果和上面的utf8不对应,则可能出现乱码现象

3 初始化游标

4 使用游标.execute('sql')语句负责向MySQL数据库传递消息。

对于数据库的操作有 增insert 删 delete 改 update 等 查 select show 等

5 提交

创建完成后需要提交,如果不提交则不生效,提交使用的是创建的链接的关键字。

6 关闭链接

需要关闭链接,首先需要关闭的是游标,其次是链接。

7 查看

在MySQL数据库中进行查看:

3 数据库进阶

1 显示设置

显示与数据库查询相似的结果show 和 select

数据库中的显示

再次创建一个数据表以备查询所用

1 进行查看显示

使用游标.fetchone()表示每次查看一行操作,两个表示两个操作一起输出

2 显示所有查看的结果

3 显示指定的数量

4 进行查看使用cur.scroll(0,'absolute')

将其恢复游标到起始位置,可以进行多次查看,如果没有此配置,默认重上一次查询的下一行开始查询

2 多行插入

1 使用for 循环遍历的方式插入:

查看

2 将sql 语句与cur.execute 分离的方式插入

查看

3 进行多行插入

查看

当%s 没有双引号时:

查看

4 :数据库应用:

1 生成姓名

查看生成结果:

2 判断数据库的某个表是否存在

3 应用封装mysql数据库的类

查看是否生成:

三 pymysql

1 安装pymysql

1 安装

pymysql 是第三方模块库,需要安装

pip install pymysql

2 参数简介和基本链接

1 基本参数详解

pymysql.connect() 方法返回的是connections模块下的connection类实例,connect方法传递就是给connection类的__init__提供参数

源码如下

def __init__(self, host=None, user=None, password="",

database=None, port=0, unix_socket=None,

charset='', sql_mode=None,

read_default_file=None, conv=None, use_unicode=None,

client_flag=0, cursorclass=Cursor, init_command=None,

connect_timeout=10, ssl=None, read_default_group=None,

compress=None, named_pipe=None,

autocommit=False, db=None, passwd=None, local_infile=False,

max_allowed_packet=16*1024*1024, defer_connect=False,

auth_plugin_map=None, read_timeout=None, write_timeout=None,

bind_address=None, binary_prefix=False, program_name=None,

server_public_key=None):

上述初始化参数中autocommit=False,则指的是默认的事务提交是关闭的,及需要手动提交事务

Connection.ping() 方法,测试数据库服务器是否活着,有一个参数热connection表示断开与服务器连接是否重连

def ping(self, reconnect=True):

"""

Check if the server is alive.

:param reconnect: If the connection is closed, reconnect.

:raise Error: If the connection is closed and reconnect=False.

"""

if self._sock is None:

if reconnect:

self.connect()

reconnect = False

else:

raise err.Error("Already closed")

try:

self._execute_command(COMMAND.COM_PING, "")

self._read_ok_packet()

except Exception:

if reconnect:

self.connect()

self.ping(False)

else:

raise

2 conn.ping 相关测试

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

conn=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

finally:

if conn:

print('关闭链接:',conn.ping(False))

conn.close()

结果如下

3 游标 Cursor

操作数据库,必须使用游标,需要先获取一个游标对象

Connection.cursor(cursor=None) 方法返回一个新的游标对象

连接没有关闭之前,游标对象可以反复使用

cursor参数,可以指定一个Cursor类,如果为None,则使用默认Cursor类

数据库操作需要使用Cursor 类的实例,提供的execute()方法,执行SQL语句,成功返回影响行数。

基本代码如下

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

conn=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

# 获取游标

cursor=conn.cursor()

sql="insert into t(id,username,password) values(3,'mysql','mysql')"

line=cursor.execute(sql)

# 此处未提交事务。若关闭,则直接导致事务回滚

print (line)

cursor.close()

finally:

if conn:

print('关闭链接:',conn.ping(False))

conn.close()

结果如下

数据库结果如下

4 添加事务管理

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

conn=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

# 获取游标

cursor=conn.cursor()

sql="insert into t(id,username,password) values(3,'mysql','mysql')"

line=cursor.execute(sql)

# 此处未提交事务。若关闭,则直接导致事务回滚

print (line)

cursor.close()

# 若没有异常,则提交事务

conn.commit()

except: # 若存在异常,则回滚事务

conn.rollback()

finally:

if conn:

print('关闭链接:',conn.ping(False))

conn.close()

结果如下

数据库结果如下

5 批量增加数据

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

# 获取游标

cursor=conn.cursor()

for i in range(5):

sql="insert into t(id,username,password) values(3,'mysql','mysql')"

line=cursor.execute(sql)

print (line)

# 此处未提交事务。若关闭,则直接导致事务回滚

# 若没有异常,则提交事务

conn.commit()

except: # 若存在异常,则回滚事务

conn.rollback()

finally:

if cursor:

cursor.close()

if conn:

conn.close()

数据库结果如下

变量的方式插入多行数据

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

# 获取游标

cursor=conn.cursor()

for i in range(10,15):

sql="insert into t(id,username,password) values({},'mysql','mysql')".format(i)

line=cursor.execute(sql)

# 此处未提交事务。若关闭,则直接导致事务回滚

# 若没有异常,则提交事务

conn.commit()

except: # 若存在异常,则回滚事务

conn.rollback()

finally:

if cursor:

cursor.close()

if conn:

conn.close()

结果如下

6 查询返回结果

1 概念

cursor类的获取查询结果集的方法有fetchone(),fetchmany(size=None),fetchall() 三种

fetchone()方法,获取结果集的下一行

fetchmany(size=None) 方法,size指定返回的行数的行,None则返回用组

fetchall() 方法,获取所有行

返回多行,如果走到末尾,就返回空元组,否则返回一个元组,其元素就是每一行的记录,每一行的记录都装载在一个元组中。

注意:fetch操作的是结果集,结果集是保存在客户端的,也就是说fetch的时候,查询已经结束了。

2 普通元祖返回

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

# 获取游标

cursor=conn.cursor()

sql="select * from t"

line=cursor.execute(sql)

print ('获取一个',cursor.fetchone()) # 获取一个

print ('获取下面两个',cursor.fetchmany(2)) # 获取下面两个

print ('获取所有',cursor.fetchall()) # 获取所有

cursor.rownumber=0 # 游标初始化,支持负索引,当大于len的索引,则会不存在

# 此处未提交事务。若关闭,则直接导致事务回滚

# 若没有异常,则提交事务

print ('获取所有',cursor.fetchall()) # 获取所有

print ('获取一个',cursor.fetchone()) #此处无法获取到了

conn.commit()

finally:

if cursor:

cursor.close()

if conn:

conn.close()

结果如下

3 字典返回(字典游标)

Cursor类有一个Mixin的子类DictCursor

只需要cursor=conn.cursor(DictCursor)就行了

返回多行,放在列表中,元素是字典,代表行,返回是列表

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

# 获取游标

cursor=conn.cursor(DictCursor)

sql="select * from t"

line=cursor.execute(sql)

print (cursor.fetchall()) # 获取一个

finally:

if cursor:

cursor.close()

if conn:

conn.close()

结果如下

7 SQL 注入

1 概念

猜测后台数据的查询语句使用拼接字符串的方式,从而经过设计为服务端传递参数,令其拼接处特殊的字符串,返回用户想要的结果

2 常用的SQL注入方式

1 数字拼接

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

# 获取游标

cursor=conn.cursor()

sql="select * from t where id={}".format('5 or 1=1')

print (sql)

line=cursor.execute(sql)

print (cursor.fetchall()) # 获取一个

finally:

if cursor:

cursor.close()

if conn:

conn.close()

结果如下

2 字符串拼接

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

print (conn.ping(False))

# 获取游标

name="'test'"

passwd="'test' or 1=1"

cursor=conn.cursor()

sql="select * from t where username={} and password ={}".format(name,passwd)

print (sql)

line=cursor.execute(sql)

print (cursor.fetchall()) # 获取一个

finally:

if cursor:

cursor.close()

if conn:

conn.close()

结果如下

3 解决SQL 注入方式

1 概念

参数化查询,可以有效防止SQL注入,并提高查询效率

cursor.execute(query,args=None)

args, 必须是元祖,列表或者字典,如果查询字符串使用%(name)s,就必须使用字典

2 查询效率高原因

参数化查询为什么能提高效率

原因就是SQL语句缓存

数据库服务器一般都会对SQL语句编译和缓存,编译只是对SQL部分,所以参数化就算有SQL指令也不会被执行

编译过程,需要词法分析,语法分析,生成AST,优化,生成执行计划等过程,比较耗资源,服务端会先查询是否对同一条语句进行缓存,如果缓存未失效,则不需要再次编译,从而降低了编译的成本,减低了内存消耗。

可以认为SQL语句字符串就是一个key,如果使用拼接方案,每次发过去的SQL语句都不一样,都需要重新编译并缓存。

大量查询的时候,首选使用参数化查询,以节省资源。

开发时,应该使用参数化查询

注意:这里说的是查询字符串的缓存,不是查询结果的缓存>

慢查询一般用不上缓存。

3 具体代码

字典参数化查询

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

d={'name':"'test'",'passwd':"'test' or 1=1"}

cursor=conn.cursor()

sql="select * from t where username=%(name)s and password=%(passwd)s"

line=cursor.execute(sql,d)

print (cursor.fetchall()) # 获取一个

finally:

if cursor:

cursor.close()

if conn:

conn.close()

结果如下

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

d={'id': '1 or 1=1'}

cursor=conn.cursor()

sql="select * from t where id=%(id)s"

line=cursor.execute(sql,d)

print (cursor.fetchall()) # 获取一个

finally:

if cursor:

cursor.close()

if conn:

conn.close()

元祖处理

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

cursor=conn.cursor()

L1=[ (i,'admin','admin') for i in range(20,23)]

for x in L1:

sql="insert into t(id,username,password) values(%s,%s,%s)"

line=cursor.execute(sql,x)

print (line)

conn.commit()

finally:

if cursor:

cursor.close()

if conn:

conn.close()

结果如下

列表如下

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

cursor=conn.cursor()

L1=[ [i,'admin','admin'] for i in range(24,26)]

for x in L1:

sql="insert into t(id,username,password) values(%s,%s,%s)"

line=cursor.execute(sql,x)

conn.commit()

finally:

if cursor:

cursor.close()

if conn:

conn.close()

结果如下

8 上下文支持

1 查看连接和游标部分源码

1 连接上下文相关源码如下:

def __enter__(self):

"""Context manager that returns a Cursor"""

warnings.warn(

"Context manager API of Connection object is deprecated; Use conn.begin()",

DeprecationWarning)

return self.cursor()

def __exit__(self, exc, value, traceback):

"""On successful exit, commit. On exception, rollback"""

if exc:

self.rollback()

else:

self.commit()

有上述代码可得,链接在使用上下文时会自动返回cursor游标,并在链接关闭时会自动判断执行语句是否出错,若出错,则直接回滚,否则提交,但未定义相关的关闭链接的操作

2 游标相关源码

def __enter__(self):

return self

def __exit__(self, *exc_info):

del exc_info

self.close()

有上述可知,游标的上下文返回的是自己,关闭链接时游标会自动关闭链接

2 连接相关上下文代码如下

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

with conn as cursor: #此处返回一个cursor链接

sql="select * from t"

cursor.execute(sql)

print (cursor.fetchmany(5))

finally:

if cursor: #上述的代码中未使用cursor的上下文,因此此处还是需要的

cursor.close()

if conn:

conn.close()

结果如下

3 游标相关代码如下

#!/usr/bin/poython3.6

#conding:utf-8

from pymysql.connections import Connection

from pymysql.cursors import DictCursor

conn=None

cursor=None

try:

conn=Connection('192.168.1.200','test','Admin@Root123','test')

with conn as cursor: #此处返回一个cursor链接

with cursor: #此处使用cursor的上下文,默认会关闭其游标

sql="select * from t"

cursor.execute(sql)

print (cursor.fetchmany(5))

finally:

if conn:

conn.close()

结果如下

连接不应该随随便便销毁,应该形成重复使用的习惯,应该是多个cursor共享一个连接 。

四 简单连接池的实现

1 概念

这里的连接池,指的是数据库的连接池

连接池,是一个容器,里面存放着已经连接到数据库的连接,如果需要连接,使用者可以直接从池中获取一个连接,使用完后归还即可

从而减少频繁的创建,销毁数据库连接的过程,提高了性能。

2 分析

一个连接池,应该是一个可以设置大小的容器,里面存放着数据库的连接。

使用者需要连接,从池中获取一个连接,用完则需要归还。

3 设计

面向对象的设计思路,构建一个连接池

构建时,传入连接的服务器相关参数(主机,端口,用户名,密码,库名称),还有提供一个池的容量

考虑多线程的使用,使用者从池中get一个连接,用完后归还该连接即可。

4 基本代码实现

#!/usr/local/bin/python3.6

#coding:utf-8

from pymysql.connections import Connection

from threading import local

import queue

class ConnPool:

def __init__(self,size,*args,**kwargs):

self.__size=size

self.__pool=queue.Queue(size) # 此处用于保存连接

self.local=local() # 此处用于隔离线程间数据,用于对不同的conn进行区分,具体在线程基础一章所有介绍

for i in range(size): # 此处用于生成连接池,此处是创建连接

conn=Connection(*args,**kwargs) # 初始化连接

self.__pool.put(conn)

@property

def maxsize(self):

return self.__size

@property

def size(self):

return self.__pool.qsize()

def __getconn(self): # 此处用于返回conn连接

return self.__pool.get()

def __returnconn(self,conn:Connection): # 此处用于归还连接

if isinstance(conn,Connection): # 此处若是一个连接,则可用于返回

self.__pool.put(conn)

def __enter__(self): # 此处用于返回一个游标,当然可以返回一个连接

if getattr(self.local,'conn',None) is None: # 若不存在,则进行添加,若存在,则返回

self.local.conn=self.__getconn()

return self.local.conn.cursor()

def __exit__(self, exc_type, exc_val, exc_tb):

if exc_type:

self.local.conn.rollback()

else:

self.local.conn.commit()

self.__returnconn(self.local.conn)

self.local.conn=None # 此处若重置此链接,则不会导致cursor的不可用,因为cursor中保存着conn的相关信息,但若被删除,则会导致全部出错,del

# 语句不可轻易执行

pool=ConnPool(3,'192.168.1.120','root','666666','test')

with pool as cursor:

with cursor:

sql="select * from login"

cursor.execute(sql)

print (cursor.fetchall())

sql="SHOW PROCESSLIST;" #此处是SQL 本身自带的用于查看进程的命令

cursor.execute(sql)

for x in cursor:

print (x)

上述的cursor能够被遍历的原因是其中有iter方法,具体源码如下

def __iter__(self):

return iter(self.fetchone, None)

结果如下

python数据库环境详解_python中MySQL数据库相关操作相关推荐

  1. python super详解_python中super()详解

    一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1:  代码段1:  class A:   def __init__ ...

  2. python关键字详解_Python 中的关键字with详解

    在 Python 2.5 中,with关键字被加入.它将常用的 try ... except ... finally ...模式很方便的被复用.看一个最经典的例子: with open('file.t ...

  3. python中configparser详解_Python中的ConfigParser模块使用详解

    1.基本的读取配置文件 -read(filename) 直接读取ini文件内容 -sections() 得到所有的section,并以列表的形式返回 -options(section) 得到该sect ...

  4. python中的super用法详解_Python中super函数用法实例分析

    本文实例讲述了python中super函数用法.分享给大家供大家参考,具体如下: 这是个高大上的函数,在python装13手册里面介绍过多使用可显得自己是高手 23333. 但其实他还是很重要的. 简 ...

  5. python scatter参数详解_Python中scatter函数参数及用法详解

    最近开始学习Python编程,遇到scatter函数,感觉里面的参数不知道什么意思于是查资料,最后总结如下: 1.scatter函数原型 2.其中散点的形状参数marker如下: 3.其中颜色参数c如 ...

  6. python scatter参数详解_Python 中 scatter 函数参数及用法详解

    Python 中 scatter 函数参数及用法详解 Python 中 scatter 函数参数及用法详解 这里有新鲜出炉的 Python 教程, 程序狗速度看过来! Python 编程语言 Pyth ...

  7. python算术运算符详解_Python中关于算术运算符的实例详解

    这篇文章主要介绍了Python算术运算符实例详解的相关资料,需要的朋友可以参考下 Python算术运算符 以下假设变量a为10,变量b为20: 运算符 描述 实例 + 加 - 两个对象相加 a + b ...

  8. python field详解_Django中models Field详解

    在model中添加字段的格式一般为:  field_name = field_type(**field_options) 一  field options(所有字段共用) 1  null   默认为F ...

  9. python多线程详解_Python多线程详解-Python-火龙果软件

    编辑推荐: 本文来自于博客,本文详细介绍了如何使用Python操作MySQL.使用Python操作Redis及项目实战. 操作MySQL 1)Windows中安装python和pycharm 2)ub ...

最新文章

  1. MFC 加载并显示图片的四种方法
  2. C#窗体应用设置多窗体和设置启动窗体
  3. python调用高德api路径规划_Python调用高德API实现批量地址转经纬度并写入表格的功能...
  4. 每天一道LeetCode-----化简路径
  5. Scala学习:Curry化的函数
  6. Python自动化测试|如何解决前置模块及数据依赖(二)
  7. 一次redis集群连接数占满问题的排查
  8. mysql 两张大表关联_详解mysql生产环境如何快速有效的删除大表,附实验说明
  9. 计算机基础高一知识点,计算机基础全部知识点_.doc
  10. 认识端口与计算机入侵防范
  11. 2019 NeurIPS | Graph Transformer Networks
  12. 电子墨水屏标签:低功耗处理器技术
  13. 无忧·企业文档自助配置完成单点登录配置,对接企业原有组织架构
  14. 领导艺术:如何留住员工的心
  15. 计算机网络(学习过程中--持续更新)
  16. Fabric 测试网络 - 商业票据
  17. 只有170字节,最小的64位Hello World程序这样写成
  18. 成都东软学院2016年ACM冬季校赛正式赛 - 题解
  19. cocos2dx 图片资源加密解密
  20. 三边形面积(海伦公式及拓展)

热门文章

  1. 阿维塔:智驾实力派,好开真颜值
  2. 我男朋友是项目经理......
  3. 优思学院|什么是过程管理?
  4. (转)我的endnote使用经验——管理文献
  5. mysql的if else_mysql中的case when 与if else
  6. Oracle配置dblink访问PostgreSQL
  7. 【机器学习】自动编码器 - Autoencoder
  8. Android怎么用adb打开应用以及获得app包
  9. Linux定时任务,执行shell文件失败问题mailed 73 bytes of output but got status 0x004b#012报错解决
  10. 阿里内部资料,10W字总结JAVA面试题-Maven篇