热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Mysql数据库高级使用PyMySQL、SQL注入与防止、事务、索引

上文基础命令直达链接:MySQL命令行客户端常用命令汇总PyMySQL的使用在Python中连接操作mysql需要先安装第三方库pymysql,执行命令:pipinstallpym

上文基础命令直达链接:MySQL命令行客户端常用命令汇总

PyMySQL的使用

在Python中连接操作mysql需要先安装第三方库pymysql,执行命令:pip install pymysql

  • pymysql使用:
  1. 导入pymysql模块

import pymysql

  1. 创建连接对象
    调用pymysql模块中的connect()函数来创建连接对象,连接到数据库需要传入较多参数:

参数host:连接的mysql主机,如果本机 是’localhost’
参数port:连接的mysql主机的端口,默认是3306
参数user:连接的用户名
参数password:连接的密码
参数database:数据库的名称
参数charset:通信采用的编码方式,推荐使用utf8

cOnn= pymysql.connect(host="localhost",
port=3306,
user="root",
password="mysql",
database="python",
charset="utf8")

  1. 获取游标对象
    获取游标对象的目标就是要执行sql语句,完成对数据库的增、删、改、查操作。代码执行完毕应执行关闭操作.

cursor= conn.cursor()

  1. pymysql完成数据的查询操作示例

import pymysql
# 创建连接对象
cOnn= pymysql.connect(
host="localhost",
port=3306,
user="root",
password="mysql",
database="python",
charset="utf8"
)
# 获取游标对象
cursor = conn.cursor()
# 查询 SQL 语句
sql = "select * from students;"
# 执行 SQL 语句 返回值就是 SQL 语句在执行过程中影响的行数
row_count = cursor.execute(sql)
print("SQL 语句执行影响的行数%d" % row_count)
# 取出结果集中一行数据, 例如:(1, '张三')
# print(cursor.fetchone())
# 取出结果集中的所有数据, 例如:((1, '张三'), (2, '李四'), (3, '王五'))
for line in cursor.fetchall():
print(line)
# 关闭游标
cursor.close()
# 关闭连接
conn.close()

  1. pymysql完成对数据的增删改示例
    代码中使用的commit()和rollback()方法为事务的操作,在我另一篇文章单独讲到.

import pymysql
# 创建连接对象
cOnn= pymysql.connect(
host="localhost",
port=3306,
user="root",
password="mysql",
database="python",
charset="utf8"
)
# 获取游标对象
cursor = conn.cursor()
try:
# 添加 SQL 语句
# sql = "insert into students(name) values('胖太'), ('老师');"
# 删除 SQ L语句
# sql = "delete from students where id = 5;"
# 修改 SQL 语句
sql = "update students set name = '夏目' where id = 5;"
# 执行sql语句
row_count = cursor.execute(sql)
print("SQL语句影响的行数为%d" % row_count)
# 提交事务
conn.commit()
except Exception as e:
print(e)
# 提交失败,回滚事务,即撤销刚执行的SQL操作
conn.rollback()
# 关闭游标
cursor.close()
# 关闭链接
conn.close()

conn.commit() 表示将修改操作提交到数据库
conn.rollback() 表示回滚数据

SQL注入与防止
  • SQL注入是什么?
    用户提交带有恶意的数据与SQL语句进行字符串方式拼接,从而影响后台SQL语句的含义,最终产生数据泄露的现象.
    例如,当前存在数据库”jing_dong”,其中有数据表”goods”,此表中存放有大量商品信息。
    在下面代码中模拟用户查询输入:

import pymysql
# 创建连接对象
cOnn= pymysql.connect(host='localhost',port=3306,user='root',password='mysql',database='jing_dong',charset='utf8')
find_name = input("请输入商品名称:")
# 获取游标对象
cursor = conn.cursor()
sql = "select * from goods WHERE name = '%s'" % find_name
print("实际后台执行的SQL语句为:",sql)
count = cursor.execute(sql)
print("SQL语句影响的行数:%d" % count)
# 获取查询结果
result = cursor.fetchall()
print(result)
cursor.close()
conn.close()

用户正常输入时,将返回我们需要的指定商品信息:

请输入商品名称:商务双肩背包
实际后台执行的SQL语句为: select * from goods WHERE name = '商务双肩背包'
SQL语句影响的行数:2
((19, '商务双肩背包', 6, 6, Decimal('99.000'), b'\x01', b'\x00'), (21, '商务双肩背包', 6, 6, Decimal('99.000'), b'\x01', b'\x00'))

用户恶意输入时,将会出现整体数据泄露的问题:

请输入商品名称:' or 1=1 or '
实际后台执行的SQL语句为: select * from goods WHERE name = '' or 1=1 or ''
SQL语句影响的行数:21
((1, 'r510vc 15.6英寸笔记本', 5, 2, Decimal('3399.000'), b'\x01', b'\x00'), (2, 'y400n 14.0英寸笔记本电脑', 5, 7, Decimal('4999.000'), b'\x01', b'\x00'), (3, 'g150th 15.6英寸游戏本', 4, 9, Decimal('8499.000'), b'\x01', b'\x00'), (4, 'x550cc 15.6英寸笔记本', 5, 2, Decimal('2799.000'), b'\x01', b'\x00'), (5, 'x240 超极本', 7, 7, Decimal('4880.000'), b'\x01', b'\x00'), (6, 'u330p 13.3英寸超极本', 7, 7, Decimal('4299.000'), b'\x01', b'\x00'), (7, 'svp13226scb 触控超极本', 7, 6, Decimal('7999.000'), b'\x01', b'\x00'), (8, 'ipad mini 7.9英寸平板电脑', 2, 8, Decimal('1998.000'), b'\x01', b'\x00'), (9, 'ipad air 9.7英寸平板电脑', 2, 8, Decimal('3388.000'), b'\x01', b'\x00'), (10, 'ipad mini 配备 retina 显示屏', 2, 8, Decimal('2788.000'), b'\x01', b'\x00'), (11, 'ideacentre c340 20英寸一体电脑 ', 1, 7, Decimal('3499.000'), b'\x01', b'\x00'), (12, 'vostro 3800-r1206 台式电脑', 1, 5, Decimal('2899.000'), b'\x01', b'\x00'), (13, 'imac me086ch/a 21.5英寸一体电脑', 1, 8, Decimal('9188.000'), b'\x01', b'\x00'), (14, 'at7-7414lp 台式电脑 linux )', 1, 3, Decimal('3699.000'), b'\x01', b'\x00'), (15, 'z220sff f4f06pa工作站', 3, 4, Decimal('4288.000'), b'\x01', b'\x00'), (16, 'poweredge ii服务器', 3, 5, Decimal('5388.000'), b'\x01', b'\x00'), (17, 'mac pro专业级台式电脑', 3, 8, Decimal('28888.000'), b'\x01', b'\x00'), (18, 'hmz-t3w 头戴显示设备', 6, 6, Decimal('6999.000'), b'\x01', b'\x00'), (19, '商务双肩背包', 6, 6, Decimal('99.000'), b'\x01', b'\x00'), (20, 'x3250 m4机架式服务器', 3, 1, Decimal('6888.000'), b'\x01', b'\x00'), (21, '商务双肩背包', 6, 6, Decimal('99.000'), b'\x01', b'\x00'))

此处数据表内的全部信息都返回给了用户,原因在于用户恶意输入的内容和后台SQL查询语拼接,导致语义改变,最终产生数据泄露。
使SQL语义改变的最终原因就是字符串拼接产生的漏洞

  • 防止SQL注入
    1. SQL语言中的参数使用%s来占位,此处不是python中的字符串格式化操作

    2. 将SQL语句中%s占位所需要的参数存在一个列表中,把参数列表传递给execute方法中第二个参数
      代码示例:

import pymysql
# 创建连接对象
cOnn= pymysql.connect(host='localhost',port=3306,user='root',password='mysql',database='jing_dong',charset='utf8')
find_name = input("请输入商品名称:")
# 获取游标对象
cursor = conn.cursor()
# 构造参数列表
params = [find_name]
sql = "select * from goods WHERE name = %s"
count = cursor.execute(sql,params)
# 注意:
# 如果要是有多个参数,需要进行参数化
# 那么params = [数值1, 数值2....],此时sql语句中有多个%s即可
# %s 不需要带引号
print("SQL语句影响的行数:%d" % count)
# 获取查询结果
result = cursor.fetchall()
print(result)
cursor.close()
conn.close()

这样就不能再通过利用参数对SQL语句进行字符串拼接改变语义了。

事务

事务就是用户定义的一系列执行SQL语句的操作, 这些操作要么完全地执行,要么完全地都不执行, 它是一个不可分割的工作执行单元。

事务的使用场景:
在日常生活中,有时我们需要进行银行转账,这个银行转账操作背后就是需要执行多个SQL语句,假如这些SQL执行到一半突然停电了,那么就会导致这个功能只完成了一半,这种情况是不允许出现,要想解决这个问题就需要通过事务来完成。

  • 事务的四大特性
    1. 原子性(Atomicity):
      事务内不可分割,要么全部提交执行,要么全部回滚不执行。
    2. 一致性(Consistency):
      在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
    3. 隔离性(Isolation):
      一个事务所做的修改操作在提交事务之前,对于其他事务来说是不可见的。数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
    4. 持久性(Durability):
      事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
  • MySQL数据库支持的表的存储引擎

— 查看MySQL数据库支持的表的存储引擎
show engines;

说明:常用的表的存储引擎是 InnoDB 和 MyISAM;
1. InnoDB 是支持事务的
2. MyISAM 不支持事务,优势是访问速度快,对事务没有要求或者以select、insert为主的都可以使用该存储引擎来创建表

  • 开启事务/提交事务

    1. 开启事务有两种方式:
      在开启事务的语句后的sql语句将遵循事务的特性成为一个整体。

    begin;
    start transaction;

    1. 提交事务:
      将本地缓存文件中的数据提交到物理表中,完成数据的更新。

    commit;

    1. 回滚事务
      放弃本地缓存文件中的缓存数据, 表示回到开始事务前的状态

    rollback;

说明:

  • 开启事务后执行修改命令,变更数据会保存到本地缓存文件中,而不维护到物理表中

  • MySQL数据库默认采用自动提交(autocommit)模式,如果没有显示的开启一个事务,那么每条sql语句都会被当作一个事务执行提交的操作

  • 使用命令select @@autocommit;查看当前自动提交事务的设置状态,默认为1,即每行sql语句自动提交事务。

  • 当设置autocommit=0就是取消了自动提交事务模式,直到显示的执行commitrollback表示该事务结束。

  • set autocommit = 0 表示取消自动提交事务模式,需要手动执行commit完成事务的提交

  • pymysql 里面的 conn.commit() 操作就是提交事务

  • pymysql 里面的 conn.rollback() 操作就是回滚事务

索引

索引在MySQL中也叫做“键”,它是一个特殊的文件,它保存着数据表里所有记录的位置信息,更通俗的来说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。

应用场景:
当数据库中数据量很大时,查找数据会变得很慢,我们就可以通过索引来提高数据库的查询效率。

  • 查看表中已有索引:

show index from 表名;

  • 主键列会自动创建索引
  • 为字段添加索引(示例为goods表name字段添加名为index_name的索引):

alter table goods add index index_name(name);

  • 联合索引

— 创建联合索引
alter table goods add index (name,price);

  1. 联合索引又叫复合索引,即一个索引覆盖表中两个或者多个字段,一般用在多个字段一起查询的时候。
  2. 减少磁盘空间开销,因为每创建一个索引,其实就是创建了一个索引文件,索引文件过多会增加磁盘空间的开销。
  • 联合索引最左原则

在使用联合索引的查询数据时候一定要保证联合索引的最左侧字段出现在查询条件里面,否则联合索引失效

在使用联合索引的时候,我们要遵守一个最左原则,即index(name,price)支持 name 、name 和 price 组合查询,而不支持单独 price 查询,因为没有用到创建的联合索引。

  • MySQL中索引的优点和缺点和使用原则
    优点:加快数据的查询速度
    缺点:创建索引会耗费时间和占用磁盘空间,并且随着数据量的增加所耗费的时间也会增加

使用原则:
1. 通过优缺点对比,不是索引越多越好,而是需要自己合理的使用。
2. 对经常更新的表就避免对其进行过多索引的创建,对经常用于查询的字段应该创建索引,
3. 数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。
4. 在一字段上相同值比较多不要建立索引,比如在学生表的”性别”字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可是建立索引。


推荐阅读
  • 在运行于MS SQL Server 2005的.NET 2.0 Web应用中,我偶尔会遇到令人头疼的SQL死锁问题。过去,我们主要通过调整查询来解决这些问题,但这既耗时又不可靠。我希望能找到一种确定性的查询模式,确保从设计上彻底避免SQL死锁。 ... [详细]
  • 本文介绍了如何在 SQL Server 2005 中创建和使用数据库快照,包括创建数据库、数据表、插入数据、创建快照、查询快照数据以及使用快照进行数据恢复等操作。 ... [详细]
  • 本文介绍了 Oracle SQL 中的集合运算、子查询、数据处理、表的创建与管理等内容。包括查询部门号为10和20的员工信息、使用集合运算、子查询的注意事项、数据插入与删除、表的创建与修改等。 ... [详细]
  • 理解GiST索引的空间构造原理
    通过空间思维解析GiST索引的构建方式及其在空间数据检索中的应用。 ... [详细]
  • MySQL 5.7 服务端在 Windows 上的安装与配置
    本文详细介绍了在 Windows 系统上安装和配置 MySQL 5.7 服务端的方法,包括 my.ini 配置文件的设置、初始化数据库、启动服务以及设置用户权限等步骤。 ... [详细]
  • 本文介绍了如何在 SQL Server (MSSQL) 数据库中更新 XML 列中的属性和节点内容。 ... [详细]
  • 图数据库与传统数仓实现联邦查询使用CYPHER实现从关系数据库过滤时间序列指标一、MySQL得到研报实体在Oracle中的唯一ID二、Oracle中过滤时间序列数据三、CYPHER ... [详细]
  • Java毕业设计项目:“传情旧物”网站(含源码与数据库)
    本项目介绍了如何配置和运行“传情旧物”网站,包括所需的技术栈、环境配置以及具体的操作步骤。 ... [详细]
  • iOS snow animation
    CTSnowAnimationView.hCTMyCtripCreatedbyalexon1614.Copyright©2016年ctrip.Allrightsreserved.# ... [详细]
  • 周排行与月排行榜开发总结
    本文详细介绍了如何在PHP中实现周排行和月排行榜的开发,包括数据库设计、数据记录和查询方法。涉及的知识点包括MySQL的GROUP BY、WEEK和MONTH函数。 ... [详细]
  • 本文介绍了如何在 Spring Boot 项目中使用 spring-boot-starter-quartz 组件实现定时任务,并将 cron 表达式存储在数据库中,以便动态调整任务执行频率。 ... [详细]
  • Docker 环境下 MySQL 双主同步配置指南
    本文介绍了如何在 Docker 环境中配置 MySQL 的双主同步,包括目录结构的创建、配置文件的编写、容器的创建与设置以及最终的验证步骤。 ... [详细]
  • MySQL Server 8.0.28 升级至 8.0.30 的详细步骤
    为了修复安全漏洞,本文档提供了从 MySQL Server 8.0.28 升级到 8.0.30 的详细步骤,包括备份数据库、停止和删除旧服务、安装新版本以及配置相关环境变量。 ... [详细]
  • 使用Tkinter构建51Ape无损音乐爬虫UI
    本文介绍了如何使用Python的内置模块Tkinter来构建一个简单的用户界面,用于爬取51Ape网站上的无损音乐百度云链接。虽然Tkinter入门相对简单,但在实际开发过程中由于文档不足可能会带来一些不便。 ... [详细]
  • 目录预备知识导包构建数据集神经网络结构训练测试精度可视化计算模型精度损失可视化输出网络结构信息训练神经网络定义参数载入数据载入神经网络结构、损失及优化训练及测试损失、精度可视化qu ... [详细]
author-avatar
mobiledu2502891447
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有