Python学习—数据库篇之SQL补充

一、SQL注入问题

在使用pymysql进行信息查询时,推荐使用传参的方式,禁止使用字符串拼接方式,因为字符串拼接往往会带来sql注入的问题

 1 # -*- coding:utf-8 -*-
 2 # author: cdc
 3 # date: 2019/3/18
 4
 5 import pymysql
 6
 7 conn = pymysql.connect(host=‘127.0.0.1‘,port=3306,user=‘root‘,password=‘cdc19951216‘,db=‘test‘,charset=‘utf8‘)
 8
 9 cursor = conn.cursor()
10
11 # 传参方式查询数据
12 cursor.execute(‘select * from user_info where name=%s and password=%s‘,(‘cdc‘,‘123456‘,))
13 res = cursor.fetchone()
14 print(res)
15
16 # 执行结果  >>>>  (1, ‘cdc‘, ‘123456‘)

传参方式查询

 1 # -*- coding:utf-8 -*-
 2 # author: cdc
 3 # date: 2019/3/18
 4
 5 import pymysql
 6
 7 conn = pymysql.connect(host=‘127.0.0.1‘,port=3306,user=‘root‘,password=‘cdc19951216‘,db=‘test‘,charset=‘utf8‘)
 8
 9 cursor = conn.cursor()
10
11 # 字符串拼接方式查询
12 sql = ‘select * from user_info where name="%s" and password="%s"‘
13 inp = (‘cdc‘,‘123456‘)
14 sql = sql % inp
15 cursor.execute(sql)
16 res = cursor.fetchone()
17 print(res)
18
19 # 执行结果  >>>>>  (1, ‘cdc‘, ‘123456‘)

字符串拼接方式查询

乍一看,两种方式都可以执行成功,但是只要对字符串拼接的方法稍微改动一下就能很明显的看出此类方式的弊端

# -*- coding:utf-8 -*-
# author: cdc
# date: 2019/3/18

import pymysql

conn = pymysql.connect(host=‘127.0.0.1‘,port=3306,user=‘root‘,password=‘cdc19951216‘,db=‘test‘,charset=‘utf8‘)

cursor = conn.cursor()

sql = ‘select * from user_info where name="%s" and password="%s"‘
inp = (‘cdc" and 1=1 -- ‘,‘123456‘)
sql = sql % inp
cursor.execute(sql)
res = cursor.fetchone()
print(res)

# 执行结果  >>>>>  (1, ‘cdc‘, ‘123456‘)

按理来说,数据库中并未满足条件的数据,但是还是可以执行成功,这是因为将字符串‘cdc" and 1=1 -- ‘替换掉对应的占位符后会将sql语句变为:

1 select * from user_info where name="cdc" and 1=1 -- " and password="%s"

此时后面password的条件已经被注释掉了,真正执行的判断条件是name=‘cdc‘和1=1,这个条件恒为true,因此无论如何都可以从数据库中查询到信息,因此使用字符串拼接的方式进行查询风险很大。

二、视图

视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,并可以将其当作表来使用。(实例化来说,可能某个需求需要重复的对某张表中的某些数据进行反复操作,每次重写重复的sql与是十分没有必要的,可以先将要操作的数据提取出来,作为一张临时的表)

1、创建视图

1 --格式:CREATE VIEW 视图名称 AS  SQL语句
2
3 CREATE VIEW temp1 AS SELECT no,name from tb3 where tb3.part_no>2

2、删除视图

1 --格式:DROP VIEW 视图名称
2
3 DROP VIEW temp1

3、修改视图

1 -- 格式:ALTER VIEW 视图名称 AS SQL语句
2
3 ALTER VIEW temp1 AS SELECT no,name,part_no FROM tb3 WHERE part_no!=1 

4、使用视图

使用视图时,将其当作表进行操作即可,由于视图是虚拟表,所以无法使用其对真实表进行创建、更新和删除操作,仅能做查询用。

1 select * from v1

三、存储过程

存储过程是一个SQL语句集合,当主动去调用存储过程时,其中内部的SQL语句会按照逻辑执行。(进一步提升了视图的简洁性和功能,使用方式类似于python中函数调用)

1、创建存储过程

 1 -- 创建存储过程
 2
 3 delimiter //
 4 create procedure p1()
 5 BEGIN
 6     select * from tb3;
 7 END//
 8 delimiter ;
 9
10 -- delimiter的作用是修改sql语句执行结束的判断标志,即若按照原来的方式,每当遇到 ; 则sql语句输入结束并运行,这样后面的END就不会生效,现先将执行结束的标志改为 // ,sql语句遇到//时才表示结束

 1 # ***************  终端调用  ****************
 2 call p1()
 3
 4 # *************  pymysql调用  *****************
 5 import pymysql
 6 # 创建连接
 7 conn = pymysql.connect(host=‘127.0.0.1‘, port=3306, user=‘root‘, passwd=‘cdc19951216‘, db=‘test‘,charset=‘utf8‘)
 8 # 创建游标
 9 cursor = conn.cursor()
10 cursor.callproc(‘p1‘)
11
12 result = cursor.fetchone()
13 print(result)
14
15 # 关闭游标
16 cursor.close()
17 # 关闭连接
18 conn.close()

调用存储过程

对于存储过程,可以接收参数,其参数有三类:

  • in          仅用于传入参数用
  • out        仅用于返回值用
  • inout     既可以传入又可以当作返回值

 1 -- 创建存储过程
 2 delimiter \ 3 create procedure p1(
 4     in i1 int,  -- 可以理解为i1为整型参数,且只提供输入值的功能,使用前必须赋值
 5     in i2 int,
 6     inout i3 int, -- 可以理解为i3为整型参数,既要提供输入值又要提供返回值的功能,使用前必须赋值
 7     out r1 int  -- 可以理解为r1为整型参数,且只提供返回值的功能,开始时不必赋值,如果有值也会被后期覆盖掉
 8 )
 9 BEGIN
10     DECLARE temp1 int; -- 定义一个整型变量temp1
11     DECLARE temp2 int default 0; -- 定义一个整型变量temp2,初始值为0
12
13     set temp1 = 1; -- 赋值
14
15     set r1 = i1 + i2 + temp1 + temp2; -- r1 = 1+2+1+0
16
17     set i3 = i3 + 100; -- i3=4+100
18
19 end\20 delimiter ;
21
22 -- 执行存储过程
23 set @t1 =4;
24 set @t2 = 0;
25 CALL p1 (1, 2 ,@t1, @t2);
26 SELECT @t1,@t2; -- 最后返回的是i3和r1的值

有参数的存储过程

To be continue... ...

原文地址:https://www.cnblogs.com/cdc1216/p/10556052.html

时间: 2024-10-18 06:32:05

Python学习—数据库篇之SQL补充的相关文章

Python学习—数据库篇之SQL语句

一.数据库级别 1.显示数据库 show databases; 默认数据库: mysql - 用户权限相关数据 test - 用于用户测试数据 information_schema - MySQL本身架构相关数据 2.创建数据库 # utf-8 (推荐使用) CREATE DATABASE 数据库名称 DEFAULT CHARSET utf8 COLLATE utf8_general_ci; # gbk CREATE DATABASE 数据库名称 DEFAULT CHARACTER SET gb

Python学习—数据库篇之索引

原文地址:https://www.cnblogs.com/cdc1216/p/10604727.html

Python学习基础篇第一篇——快速入门(适合初学者)

一.Python学习基础篇第一篇--(快速入门) 建议从Python2.7开始学习,Python2.7可以支持扩展大量的第三方类库,是目前比较成熟的版本 编写代码的软件推荐将python自带的IDLE和PyCharm集成IDE结合起来使用 1.1 Python命令行 Python命令行将以 >>> 开始,比如 >>>print 'Hello World!' 对于验证简单的命令可以在python自带的IDLE中完成  1.2 在Python自带的IDLE写一段小程序 在所

Python学习—数据库操作

python2中操作数据库:MySQLdbpython3中操作数据库:pymysql python接连数据库 1.创建数据库连接: mysql.connect()函数 2.执行数据库操作:执行数据库操作,我们要使用连接对象获得一个cursor(游标)对象: 用连接对象的cursor()方法返回一个游标对象 接下来,我们会使用cursor提供的方法来进行工作. 这些方法包括两大类:1.执行命令,2.接收返回值 执行命令: callproc(self, procname, args):用来执行存储过

Python学习基础篇—文件操作和集合

这篇博客来说一下python对文件的操作. 对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句柄操作文件 3.关闭文件. 现有以下文件file.txt: 我们哭了 我们笑着 我们抬头望天空 星星还亮着几颗 我们唱着 时间的歌 才懂得相互拥抱 到底是为了什么 因为我刚好遇见你 留下足迹才美丽 风吹花落泪如雨 因为不想分离 因为刚好遇见你 留下十年的期许 如果再相遇 我想我会记得你 我们哭了 我们笑着 我们抬头望天空 星星还亮着几颗 我们唱着 时间的歌 才懂得相互

Python学习-基础篇11 前端知识之HTML内容

HTML介绍 Web服务本质 import socket sk = socket.socket() sk.bind(("127.0.0.1", 8080)) sk.listen(5) while True: conn, addr = sk.accept() data = conn.recv(8096) conn.send(b"HTTP/1.1 200 OK\r\n\r\n") conn.secd(b"<h1>Hello world!</h

python学习之第四天补充

本节大纲 迭代器&生成器 装饰器  基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实的计算器所得出的结果一致 迭代器&

Python学习-基础篇1

一.变量: 1)变量定义规范: #1. 变量名只能是 字母.数字或下划线的任意组合#2. 变量名的第一个字符不能是数字#3. 关键字不能声明为变量名['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda',

Python学习-基础篇4 模块与包与常用模块

一 模块介绍 1.什么是模块?#常见的场景:一个模块就是一个包含了一组功能的python文件,比如spam.py,模块名为spam,可以通过import spam使用. #在python中,模块的使用方式都是一样的,但其实细说的话,模块可以分为四个通用类别: 1 使用python编写的.py文件 2 已被编译为共享库或DLL的C或C++扩展 3 把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包) 4 使用C编写并链接到python解释器的内置模块2.