1 简介
MysqL 基于TCP 协议之上的开发,但是网络连接后,传输的数据必须遵循MysqL的协议,封装好MysqL协议的包,就是驱动程序
MysqL 的驱动
MysqLDB 最有名的库,对MysqL 的C Client 封装实现,支持python2,不更新了,不支持python3
MysqL 官方的connector
pyMysqL 语法兼容MysqLdb,使用python写的库,支持python3
2 安装MysqL数据库
1 挂载镜像文件(本次使用的是本地镜像文件)
2 启动MysqL数据库
3 创建用户名和密码并刷新
grant all(表示所有操作) on .(库.表(所有的,也可以指定)) to [email protected](设置用户名为root,链接为本地链接) identified by ‘roiot123‘;(设置密码)
flush privileges;(刷新权限)
4 修改默认字符集:
server.cnf 中的操作(前面必须有空格,否则不生效,不能写入汉字)
client.cnf 操作同上
重启加载字符集
5 查看字符集是否加载完毕
如上,则表示加载完毕!!!
6 创建数据库
二 MysqL-python
1 安装
1 安装
2 查看安装是否完成,若完成,则不会报错
2 连接一般流程
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 查看
3 数据库进阶
1 显示设置
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‘,‘[email protected]‘,‘test‘) print (conn.ping(False)) finally: if conn: print(‘关闭链接:‘,conn.ping(False)) conn.close()
结果如下
3 游标 Cursor
Connection.cursor(cursor=None) 方法返回一个新的游标对象
连接没有关闭之前,游标对象可以反复使用
基本代码如下
#!/usr/bin/poython3.6 #conding:utf-8 from pyMysqL.connections import Connection conn=None try: conn=Connection(‘192.168.1.200‘,‘[email protected]‘,‘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‘,‘[email protected]‘,‘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‘,‘[email protected]‘,‘test‘) print (conn.ping(False)) # 获取游标 cursor=conn.cursor() for i in range(5): sql="insert into t(id,‘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‘,‘[email protected]‘,‘test‘) print (conn.ping(False)) # 获取游标 cursor=conn.cursor() for i in range(10,15): sql="insert into t(id,password) values({},‘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‘,‘[email protected]‘,‘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‘,‘[email protected]‘,‘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‘,‘[email protected]‘,‘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‘,‘[email protected]‘,‘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 概念
cursor.execute(query,args=None)
args,必须是元祖,列表或者字典,如果查询字符串使用%(name)s,就必须使用字典
2 查询效率高原因
参数化查询为什么能提高效率
原因就是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‘,‘[email protected]‘,‘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‘,‘[email protected]‘,‘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‘,‘[email protected]‘,‘test‘) cursor=conn.cursor() L1=[ (i,‘admin‘,‘admin‘) for i in range(20,23)] for x in L1: sql="insert into t(id,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‘,‘[email protected]‘,‘test‘) cursor=conn.cursor() L1=[ [i,‘admin‘] for i in range(24,26)] for x in L1: sql="insert into t(id,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‘,‘[email protected]‘,‘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‘,‘[email protected]‘,‘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共享一个连接 。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。