目录
一、正则表达式的概述
1、基本介绍
正则表达式,也叫做规则表达式,通常会说成【正则】。
实际上,正则表达式就是指符合一定规则的字符串,同时它能用于检查一段文本数据是否与某种模式匹配。
比如,在网站注册新用户时,对用户名、手机号等的验证就使用了正则表达式。
在Python中,有一个专门用于处理正则表达式的模块:
python
# 导入模块
import re
在正则表达式中,可以使用单个字符或一段字符串来匹配满足正则规则的文本数据。而我们要学习的,就是正则规则。
在一些文本编辑器中,可以使用正则表达式来查找或替换一些文本。
总结:
(1)正则表达式就是一段具有特殊含义的字符串,即正则表达式 == 字符串;
(2)注意:在Python中,若要操作正则表达式,要使用re模块。
2、快速使用re模块
我们已经知道,可以使用re模块来操作正则表达式。
re模块常用方法:
函数名 | 含义 |
---|---|
match(pattern, string) | 返回一个已匹配成功的对象。其中,参数pattern表示正则字符串,参数string表示要匹配的内容。 |
当成功匹配数据后,结果存放在对象的函数:
函数名 | 含义 |
---|---|
group(num=0) | 匹配成功的内容,num默认是0,表示匹配的所有数据结果。 |
例如,一起来完成:
(1)使用正则快速验证手机号码是否合格;
(2)验证手机是否合格的条件有:手机号码以1开头且总位数为11位,全部为数字且不包含其他字符;
(3)根据要求,使用re模块完成对手机号码的验证。
python
import re
str1 = '13812345678'
regex_str = '1[3456789][0-9]{9}' # 这种写法没有定义开头结尾限定,只要包含匹配的内容就行
regex_str = '^1[3456789][0-9]{9}$' # 这种写法佳乐开头结尾限定,必须精准匹配才行
result = re.match(regex_str,str1) # 判断str1这个字符串是否符合regex_str这个正则规则
if result is not None:
print('字符串内容符合正则!')
print(result.group()) # group 表示只获取字符串中匹配上的部分
else:
print('字符串内容不符合正则!')
总结:
(1)如果要使用re模块来匹配数据,应该使用re模块的match()匹配方法;
(2)注意:当使用re模块未匹配到对应的数据时,会返回None。
二、正则的常见规则
1、匹配单个字符
常用的匹配单个字符的语法:
代码 | 功能 |
---|---|
. | 匹配除\n之外的任何单个字符。 |
[ ] | 匹配[ ]中列举的字符。 |
\d | 匹配一个数字字符,比如[0-9]。 |
\D | 匹配一个非数字字符,比如[^0-9] 。 |
\s | 匹配任何空白字符。(空格、tab、换行) |
\S | 匹配任何非空白字符。 |
\w | 匹配非特殊字符,比如a-z、A-Z、0-9、_、汉字。 |
\W | 匹配特殊字符,比如非字母、非数字、非汉字等。 |
例如,一起来完成:
(1)使用.来匹配任意单个字符;
(2)使用[a-z]、[A-Z]、[^0-9]
分别来查看小写字母、大写字母、非数字;
(3)使用\d来匹配一个数字字符;
(4)使用\w来匹配一个可能有数字、大小写字母、下划线的单个字符。
python
# 1.导入模块
import re
# 报错:正则有误; 能输出结果,表示正常
# print(f"结果:{xxx}")
# 2.任意字符
print(f"结果:{re.match('.','h').group()}")
print(f"结果:{re.match('.','1').group()}")
print(f"结果:{re.match('.','_').group()}")
print(f"结果:{re.match('.','python').group()}")
# 3.小写、大写、非数字
print(f"结果:{re.match('[a-z]','a').group()}")
print(f"结果:{re.match('[a-z]','y').group()}")
print(f"结果:{re.match('[a-z]','Z').group()}") # 报错
print(f"结果:{re.match('[a-z]','abc').group()}")
print(f"结果:{re.match('[A-Z]','B').group()}")
print(f"结果:{re.match('[0-9]','1').group()}")
print(f"结果:{re.match('[^0-9]','b').group()}")
print(re.match('\D','b').group())
# 4.一个数字
print(f"结果:{re.match('[0-9]','8').group()}")
print(f"结果:{re.match('[0-9]','66').group()}")
print(re.match('\d','6').group())
5.单字符
print(re.match('\w','6').group())
print(re.match('\w','a').group())
print(re.match('\w','N').group())
print(re.match('\w','_').group())
print(re.match('\w','深圳').group())
2、原始字符串
原始字符串指的是:在所有的正则表达式前,最好加上r,语法:
python
r"正则表达式"
例如,一起来完成:
(1)请使用正则来匹配路径名:E:\\
;
(2)请尝试使用不同方式去匹配数据,观察效果;
(3)思考:当要定义一段批量文本内容时,该怎么定义字符串?
python
print('E:\a.txt') # 这里 会把 \a 当成一个字符, \是转义字符
print('E:\\a.txt') # \\ 合成 一个 \
print(r'E:\a.txt') # 前边加 r 表示 字符串中的任何字符没有特殊函数,就是普通字符串,不要过度解读
总结:
(1)当不想给一段文本数据内容转义而又要表达原始意义时,可以在文本数据内容前添加r。
(2)注意:当正确写了正则后又匹配不出数据结果时,可以试试在正则前添加r解决问题。
3、匹配多个字符
常用的匹配多个字符的语法:
代码 | 功能 |
---|---|
X* | 匹配X出现0次或无限次,即可有可无。 |
X+ | 匹配X出现1次或无限次,即至少有1次。 |
X? | 匹配X出现1次或0次,即有一次或一次也没有。 |
X{m} | 匹配X恰好出现m次。 |
X{m,n} | 匹配X至少m次,但是不超过n次。 |
例如,一起来完成:
(1)使用X*来匹配出一个字符串:第1个字母为大小写字母,后面都是小写字母且这些字母可有可无;
(2)通过X+来匹配一个具有数字、大小写字母、下划线的字符串;
(3)通过X?来匹配0到99之间的任意数字;
(4)通过X{n,m}匹配出5到16位的密码,可以是大小写英文字母、数字、下划线。
python
import re
result = re.match("","").group()
print(f"结果:{result}")
# X*
result = re.match("[a-zA-Z]","x").group()
result = re.match("[a-zA-Z]","U").group()
result = re.match("[a-zA-Z][a-z]*","U").group()
result = re.match("[a-zA-Z][a-z]*","UzogY").group()
print(f"结果:{result}")
# X+
result = re.match("\w","123abcABC_hello").group()
result = re.match("\w+","123abcABC_hello").group()
print(f"结果:{result}")
# X? 0-9 10-99
result = re.match("[1-9][0-9]","12").group()
result = re.match("[1-9][0-9]","98").group()
result = re.match("[1-9]?[0-9]","0").group()
result = re.match("[1-9]?[0-9]","17").group()
# result = re.match("[1-9]?[0-9]","09").group()
print(f"结果:{result}")
# X{m,n}
result = re.match("[a-zA-Z0-9_]{5,16}","123456").group()
result = re.match("[a-zA-Z0-9_]{5,16}","1234fjwoefwoe23__fwjelf").group() # ?如何解决? $
print(f"结果:{result}")
==总结:==
(1)使用匹配多个字符的方式,可以一个字符或批量数据内容;
(2)注意:当要匹配批量数据内容时,应该优先使用:*。
4、匹配开头和结尾
代码 | 功能 |
---|---|
^ | 匹配字符串开头。 |
$ | 匹配字符串结尾。 |
例如,一起来完成:
(1)使用^来匹配非数字的单个字符;
(2)使用$来匹配<www.baidu.com>的结尾处。
python
import re
# result = re.match("","").group()
# print(f"结果:{result}")
# 匹配开头: 非数字
result = re.match("[0-9]","1aaa1").group() # 默认是从第一个字符开始匹配,如果第一个字符不是数字就结束
print(f"结果:{result}")
result = re.match("[^0-9]","g").group() # 默认是从第一个字符开始匹配
print(f"结果:{result}")
result = re.match("[^0-9]","heima").group() # 默认是从第一个字符开始匹配
print(f"结果:{result}")
result = re.match("[^0-9]+","heima").group() # 默认是从第一个字符开始匹配
print(f"结果:{result}")
print('----------------------')
# 匹配结尾
result = re.match(".+","www.baidu.com").group()
print(f"结果:{result}")
result = re.match("www.baidu.com","www.baidu.com").group()
print(f"结果:{result}")
result = re.match("www.baidu.com$","www.baidu.com.cn.gov.edu").group() # 是否以某个串结尾
print(f"结果:{result}")
result = re.match("^www.baidu.com$","www.baidu.com").group()
print(f"结果:{result}")
总结:
(1)当要限定结尾处内容时,可以使用$符号。
5、匹配分组
要获取分组数据信息,语法:
代码 | 功能 |
---|---|
X|Y | 匹配X或Y的任意一个表达式。 |
(X) | 将括号中字符X作为一个分组用于获取,且从1开始统计分组。 |
例如,一起来完成:
(1)使用X|Y来匹配出0-100之间的所有数字字符结果;
(2)使用(X)来匹配出含有163、126、qq这几个内容且用户名位数为4-12位的邮箱,如itcast@163.com等。
python
import re
result = re.match("","").group()
print(f"结果:{result}")
0-100
result = re.match("hello|world","world").group() # 只要hello和world有一个匹配上即可
print(f"结果:{result}")
result = re.match("[1-9]?[0-9]|100","8").group()
print(f"结果:{result}")
result = re.match("[1-9]?[0-9]|100","87").group()
print(f"结果:{result}")
result = re.match("[1-9]?[0-9]|100","99").group()
print(f"结果:{result}")
result = re.match("[1-9]?[0-9]|100","100").group() # 10
print(f"结果:{result}")
result = re.match("100|[1-9]?[0-9]","100").group()
print(f"结果:{result}")
result = re.match("100|[1-9]?[0-9]","10").group()
print(f"结果:{result}")
print('----------------------------------------')
# 邮箱号
result = re.match("(\w{4,12})@(126|163|qq).(com|cn)","hellopy@qq.com").group()
print(result)
print(f"结果:{result[:result.find('@')]}")
# re.match('xxxx(表达式1)xxxx(表达式2)',字符串).group(1)
# group(2) 里边的数字表示获取第2个括号中的内容
result = re.match("(\w{4,12})@(126|163|qq).com","hellopy@163.com").group(2)
print(result)
print(f"结果:{result[:result.find('@')]}")
result = re.match("(\w{4,12})@(126|163|qq).com","hellopy@163.com").group(1)
print(f"结果:{result[:result.find('@')]}")
result = re.match("(\w{4,12})@(126|163|qq).com","hellopy@163.com").group(2)
print(f"结果:{result[:result.find('@')]}")
# group 中不加数字,返回匹配的所有内容
result = re.match("(\w{4,12})@(126|163|qq).com","hellopy@qq.com").group()
print(result)
print(f"结果:{result[:result.find('@')]}")
总结:
(1)如果在涉及到要获取分组数据时,一定记得要使用()来写正则;
(2)注意:要获取分组数据时,在正则中的()从1开始计算分组,比如获取第1组,则group()的括号中应该填写1。
三、Python与MySQL交互
1、pymysql模块的安装
当要使用Python和MySQL数据库进行交互,需要借助一个第三方模块:pymysql。
在使用pymysql模块前,先进行安装:
python
pip install pymysql
有时使用pip install xxx命令安装时较慢,若要提升pip下载的速度,可采用命令:
python
pip install 模块名 [-i 镜像源地址]
pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pymysql -i http://mirrors.aliyun.com/pypi/simple/
比如,在国内的镜像源中,有很多可供使用的源地址:
镜像来源 | 镜像源地址 |
---|---|
豆瓣 | http://pypi.douban.com/simple/ |
阿里云 | Simple Index |
清华大学 | Simple Index |
中国科技大学 | Simple Index |
华中理工大学 | http://pypi.hustunique.com/ |
山东理工大学 | http://pypi.sdutlinux.org/ |
当成功安装pymysql模块后,可直接导入使用:
python
# 导入模块
import pymysql
例如,一起来完成:
(1)在Python中,使用命令安装pymysql模块;
(2)当成功安装模块后,即可导入并验证是否已成功安装;
(3)思考:还有其他方式安装模块吗?
总结:
(1)当要在Python中安装pymysql模块,可以使用pip install pymsql命令;
(2)注意:当要使用pymysql模块时,可以直接导入使用,语法:import pymysql。
2、pymysql的操作步骤
在Python中,使用pymysql模块来操作MySQL数据的基本步骤:
对于图解,操作步骤说明:
(1)导入模块;
(2)创建连接对象;
(3)创建游标对象;
(4)使用游标对象执行SQL并进行增删改查;
(5)关闭游标对象;
(6)关闭连接对象。
例如,一起来了解:
(1)操作pymysql模块的基本步骤;
(2)对各个步骤做详细说明。
python
(1)导入模块;
导入模块前, 优先安装pymysql模块: pip install pymysql
import pymysql
# 使用模块操作MySQL数据库
----------------------------------
(2)创建连接对象;
db_conn = pymysql.connect()
# 用户名 root
# 密码 123456
# IP地址 127.0.0.1 localhost
# 端口号 3306
# 数据库名 班级名_db_xxx
# 编码格式 utf8 gbk
----------------------------------
(3)创建游标对象;
db_cursor = db_conn.cursor()
# 游标获取数据
----------------------------------
(4)使用游标对象执行SQL并进行增删改查;
db_cursor.execute(xxxx)
# 增 insert into 表名[(字段1, 字段2, ...)] values(值1, 值2,...)[,(值1, 值2,...),...][;]
# 删 delete from 表名 [where 条件];
# 改 update 表名 set 字段1=值1[, 字段2=值2, ...] [where 条件];
# 查 select *[字段1, 字段2, ...] from 表名 [where 条件];
----------------------------------
(5)关闭游标对象;
close()
----------------------------------
(6)关闭连接对象。
close()
总结:
(1)当操作完pymysql后,需要对连接、游标等对象资源进行关闭,可以使用close()方法;
(2)注意:为了便于使用和操作pymysql模块,建议按照操作步骤来进行处理。
3、connection对象
我们都知道,在使用MySQL数据库前,首先需要登录并进行连接。[命令行、DataGrip]
类似地,在使用pymysql模块时,也需要登录并进行连接,且此时需要使用connection对象。
connection是用于建立与数据库的连接,需要使用pymysql模块来调用:
函数 | 含义 |
---|---|
connect(host=None, port=0, user=None, password="", database=None, charset='',...) | 用于创建Connection连接对象。 ①host:表示连接MySQL的IP地址。若为本机,则可表示成'localhost'或'127.0.0.1';若为其他计算机,则表示为具体IP地址; ②port:表示连接的MySQL的端口号,默认是3306; ③user:表示连接的用户名,默认是root; ④password:表示连接的密码; ⑤database:表示数据库的名称; ⑥charset:表示采用的编码方式,设定为'utf8'即可。 |
当成功通过connect()获取并得到连接对象后,常用函数:
函数 | 含义 |
---|---|
commit() | 用于事务提交,在进行数据操作时需要进行事务提交后才会生效。 |
close() | 用于关闭连接。 |
cursor() | 用于返回cursor对象,可使用该对象来执行SQL语句并获取结果。 |
说明:
(1)使用pymysql模块时,已默认开启了事务,因此要让数据操作生效,则必须要进行事务提交;
(2)为了节约系统内存资源,通常在使用完Connection连接对象后,要进行close()关闭连接。
总结:(1)通常情况下,使用pymysql连接MySQL数据库,需要知道:IP地址、端口号、用户名、密码;
(2)注意:pymysql模块操作MySQL是默认已经开启了事务。
4、cursor对象
若要执行SQL语句时,则需要使用cursor对象,可通过connection对象的cursor()方法进行创建。
函数 | 含义 |
---|---|
cursor() | 用于返回cursor对象,可使用该对象来执行SQL语句并获取结果。 |
当有了cursor对象后,常用函数:
函数 | 含义 |
---|---|
execute(operate [, param]) | 用于执行SQL语句,返回受影响的行数。 其中,参数operate为字符串类型,表示SQL语句; 参数parameters为列表类型,表示SQL语句中的参数。 |
fetchone() | 在执行查询语句时,获取查询结果集的第一行数据,返回一个元组,即(v1, v2,...)。 |
fetchall() | 在执行查询时,获取结果集的所有行,返回一个元组,即((v11, v12,...), (v21, v22,...),...)。 |
close() | 关闭cursor对象。 |
说明:
(1)使用execute()执行SQL语句时,SQL语句应写成字符串型;
(2)当关闭connection和cursor对象时,记得先关闭cursor游标,后关闭connection连接。
总结:(1)当要使用cursor游标对象来执行SQL语句时,可以使用excute()方法;
(2)注意:在使用pymysql执行SQL语句时,要使用cursor对象来操作。
四、数据记录操作
1、准备数据表
通常情况下,在使用pymysql模块前,会先创建好数据库和数据表字段信息。
这样,可以更便于后期操作。
例如,使用MySQL命令完成:
(1)创建一个班级db_students数据库,并设定为utf8编码;
(2)在库中新建一个数据表,包含编号id、姓名name、性别gender、年龄age等字段;
(3)其中,字段编号id为整型、主键且自动增长;
(4)操作完成后,查看表结构,并查看表内是否有数据内容。
python
######################新建库和表#############################
# 创建库
create database if not exists db_students charset utf8;
# 使用库
use db_students;
# 查看表信息
show tables;
# 创建表
create table if not exists student(
id int primary key auto_increment,
name varchar(20),
gender varchar(10),
age int
) engine = InnoDB default charset utf8;
# 查看表字段
desc student;
# 查看表数据
select * from student;
总结:
(1)在操作pymysql前,请记得先创建好数据表,便于后面的程序执行。
2、插入数据
当已成功创建好了数据库和数据表,就可以使用pymysql来给表内添加数据了。使用函数:
函数 | 含义 |
---|---|
execute(operate [, param]) | 用于执行SQL语句,返回受影响的行数。 其中,参数operate为字符串类型,表示SQL语句; 参数parameters为列表类型,表示SQL语句中的参数。 |
说明:
param参数是可选项。
例如,使用pymysql模块来完成:
(1)使用execute()向学生表中插入1条学生数据;
(2)使用DataGrip查看添加成功后的数据结果;
(3)思考:如果要插入两条数据,该怎么做呢?
python
# 1、导入模块
import pymysql
# 2、创建连接对象
conn = pymysql.connect(
host='192.168.88.100',
port=3306,
user='root',
password='123456',
database= 'db_students',
charset='utf8'
)
print(conn) # 测试一下服务器是否联通
# 3、获取游标
db_cursor = conn.cursor()
# 4、使用游标来执行sql
result = db_cursor.execute("insert into student(name,gender,age) values ('刘备','男',23)")
print(result) # 返回影响的行数
# 5、增删改之后,一定要让操作生效,必须要提交事务,否则不生效
conn.commit()
# 6、关闭游标对象;
db_cursor.close()
# 7、关闭连接对象。
conn.close()
总结:
(1)当使用pymysql模块插入数据,必须使用commit()方法提交事务;
(2)注意:使用PyCharm编写程序插入数据成功后,可以到DataGrip中查看是否已成功添加数据。
3、修改数据
当数据显示有误时,就需要来修改数据内容。使用函数:
函数 | 含义 |
---|---|
execute(operate [, param]) | 用于执行SQL语句,返回受影响的行数。 其中,参数operate为字符串类型,表示SQL语句; 参数parameters为列表类型,表示SQL语句中的参数。 |
说明:
param参数是可选项。
例如,使用pymysql模块来完成:
(1)使用execute()修改学生表中id为1的数据,并把年龄修改为19岁,姓名修改为王军;
(2)使用DataGrip查看修改成功后的数据结果;
(3)思考:能否把性别为男的所有数据,性别都修改为Male呢?
python
# 1、导入模块
import pymysql
# 2、创建连接对象
conn = pymysql.connect(
host='192.168.88.100',
port=3306,
user='root',
password='123456',
database= 'db_students',
charset='utf8'
)
print(conn) # 测试一下服务器是否联通
# 3、获取游标
db_cursor = conn.cursor()
# 4、使用游标来执行sql
result = db_cursor.execute("""
update student set name = '大乔' where id = 4
""")
print(result) # 返回影响的行数
# 5、增删改之后,一定要让操作生效,必须要提交事务,否则不生效
conn.commit()
# 6、关闭游标对象;
db_cursor.close()
# 7、关闭连接对象。
conn.close()
总结:
(1)当使用pymysql模块修改数据,要使用commit()方法进行提交事务;
(2)注意:若要修改数据表的数据内容,必须先已存在该数据。
4、删除数据
当数据内容已失效时,就需要来删除数据内容。使用函数:
函数 | 含义 |
---|---|
execute(operate [, param]) | 用于执行SQL语句,返回受影响的行数。 其中,参数operate为字符串类型,表示SQL语句; 参数parameters为列表类型,表示SQL语句中的参数。 |
说明:
param参数是可选项。
例如,使用pymysql模块来完成:
(1)使用execute()删除学生表中id为2的这条数据;
(2)使用DataGrip查看删除成功后的数据结果;
(3)思考:目前,使用execute()操作数据时,都采用硬编码方式,会存在什么问题吗?
python
# 1、导入模块
import pymysql
# 2、创建连接对象
conn = pymysql.connect(
host='192.168.88.100',
port=3306,
user='root',
password='123456',
database= 'db_students',
charset='utf8'
)
print(conn) # 测试一下服务器是否联通
# 3、获取游标
db_cursor = conn.cursor()
# 4、使用游标来执行sql
result = db_cursor.execute("""
delete from student where name = '曹操'
""")
print(result) # 返回影响的行数
# 5、增删改之后,一定要让操作生效,必须要提交事务,否则不生效
conn.commit()
# 6、关闭游标对象;
db_cursor.close()
# 7、关闭连接对象。
conn.close()
总结:
(1)当要删除数据记录时,应该使用delete关键字;
(2)注意:使用pymysql模块删除数据时,也需要进行提交事务。
5、SQL注入
SQL注入指的是:恶意篡改或注入SQL条件。
当开发者的数据条件若被恶意篡改,那就达不到预期的查询效果。
为了了解SQL注入是怎么回事?通过一个案例来分析。
例如,使用命令来完成:
(1)给学生表tb_student中添加一些数据,查看效果;
(2)查询age=22的这条数据的所有信息;
(3)使用SQL注入方式来恶意篡改查询条件,比如在条件结尾处,添加or 1=1,并查询结果;
(4)思考:对比两次查询结果,该如何解决这类SQL注入问题呢?
python
# 1、导入模块
import pymysql
# 2、创建连接对象
conn = pymysql.connect(
host='192.168.88.100',
port=3306,
user='root',
password='123456',
database= 'db_students',
charset='utf8'
)
print(conn) # 测试一下服务器是否联通
# 3、获取游标
db_cursor = conn.cursor()
input_id = input('请输入你要删除的id:') # 从键盘输入: 88 or 1=1
# 4、使用游标来执行sql # 发现所有数据都被删除,因为or后边的条件永远成立,条件永远为真
result = db_cursor.execute(f"""
delete from student where id = {input_id}
""")
print(result) # 返回影响的行数
# 5、增删改之后,一定要让操作生效,必须要提交事务,否则不生效
conn.commit()
# 6、关闭游标对象;
db_cursor.close()
# 7、关闭连接对象。
conn.close()
注意:当恶意篡改了SQL条件后,查询的结果可能达不到预期效果。
6、语句参数化
如果要解决SQL注入的问题,在pymysql模块中,可采用语句参数化来解决。
语句参数化是指以%s表示值,然后再传入具体的参数值进行替换。
为了更好理解语句参数化,可以把SQL语句的参数化、值,简要地理解为print()函数中的格式化符号输出:
python
print("xxx%s, xxx%d"%(name, age))
要使用cursor对象的函数:
函数 | 含义 |
---|---|
execute(operate, param) | 用于执行SQL语句,返回受影响的行数。 其中,参数operation为字符串类型,表示具体的SQL语句,注意,若在SQL语句中要向外传入参数值,则该参数均使用%s表示; 参数parameters为列表类型,表示SQL语句中的参数。 |
说明:
param参数的类型是列表list。
例如,使用pymysql模块来完成:
(1)通过键盘录入的方式输入变化的数据值;
(2)使用语句参数化和execute()给数据表添加一条数据内容;
(3)操作完成后,使用DataGrip查看添加成功后的数据结果。
python
# 1、导入模块
import pymysql
# 2、创建连接对象
conn = pymysql.connect(
host='192.168.88.100',
port=3306,
user='root',
password='123456',
database= 'db_students',
charset='utf8'
)
print(conn) # 测试一下服务器是否联通
# 3、获取游标
db_cursor = conn.cursor()
input_id = input('请输入你要删除的id:') # 从键盘输入: 88 or 1=1
params = [input_id]
# 不管你从键盘输入什么都会当做普通字符串赋值给%s,id = '88 or 1=1' -以前--> id = 88 or 1=1
sql= "delete from student where id = %s "
# 4、使用游标来执行sql
result = db_cursor.execute(sql,params)
print(result) # 返回影响的行数
# 5、增删改之后,一定要让操作生效,必须要提交事务,否则不生效
conn.commit()
# 6、关闭游标对象;
db_cursor.close()
# 7、关闭连接对象。
conn.close()
python
# 1、导入模块
import pymysql
# 2、创建连接对象
conn = pymysql.connect(
host='192.168.88.100',
port=3306,
user='root',
password='123456',
database= 'db_students',
charset='utf8'
)
print(conn) # 测试一下服务器是否联通
# 3、获取游标
db_cursor = conn.cursor()
param = ['张飞','男',33]
sql = 'insert into student(name,gender,age) values (%s,%s,%s)'
result = db_cursor.execute(sql, param)
print(result) # 返回影响的行数
# 5、增删改之后,一定要让操作生效,必须要提交事务,否则不生效
conn.commit()
# 6、关闭游标对象;
db_cursor.close()
# 7、关闭连接对象。
conn.close()
总结:
(1)语句参数化时,必须使用%s表示参数
(2)注意:要进行语句参数化时,使用execute()方法时需要传递两个参数。
7、查询数据
查询数据,要使用cursor对象的函数:
函数 | 含义 |
---|---|
execute(operate [, param]) | 用于执行SQL语句,返回受影响的行数。 其中,参数operation为字符串类型,表示具体的SQL语句,注意,若在SQL语句中要向外传入参数值,则该参数均使用%s表示; 参数parameters为列表类型,表示SQL语句中的参数。 |
fetchone() | 在执行查询语句时,获取查询结果集的第一行数据,返回一个元组,即(v1, v2,...)。 |
fetchall() | 在执行查询时,获取结果集的所有行,返回一个元组,即((v11, v12,...), (v21, v22,...),...)。 |
说明:
查询的数据结果是元组类型。
例如,使用pymysql模块来完成:
(1)使用fetchone来查询一条某xx姓名的数据信息;
(2)使用fetchall()查询出所有数据信息,并遍历出详细信息。
python
# 1、导入模块
import pymysql
# 2、创建连接对象
conn = pymysql.connect(
host='192.168.88.100',
port=3306,
user='root',
password='123456',
database= 'db_students',
charset='utf8'
)
print(conn) # 测试一下服务器是否联通
# 3、获取游标
db_cursor = conn.cursor()
# 执行sql,进行查询
sql = 'select * from student'
db_cursor.execute(sql)
# 获取查询结果,获取一行
print(db_cursor.fetchone())
print('--------------------')
# 获取查询结果,获取多行,并遍历
result = db_cursor.fetchall()
for row2 in result:
print(row2)
# 1、导入模块
import pymysql
# 2、创建连接对象
conn = pymysql.connect(
host='192.168.88.100',
port=3306,
user='root',
password='123456',
database= 'db_students',
charset='utf8'
)
print(conn) # 测试一下服务器是否联通
# 3、获取游标
db_cursor = conn.cursor()
# 执行sql,进行查询,男性,年龄大于20岁的学生信息
gender = input('请输入你要查询的性别: ')
age = input('请输入你要查询的年龄: ')
params = [gender,age]
sql = 'select * from student where gender = %s and age > %s' # %s 表示占位符
db_cursor.execute(sql,params)
print('--------------------')
# 获取查询结果,获取多行,并遍历
result = db_cursor.fetchall()
for row2 in result:
print(row2)
# 5、增删改之后,一定要让操作生效,必须要提交事务,否则不生效
conn.commit()
# 6、关闭游标对象;
db_cursor.close()
# 7、关闭连接对象。
conn.close()
总结:
(1)当要获取所有查询结果数据时,可以使用fetchall()方法;
(2)注意:虽然查询数据无需提交事务,但还是建议提交一下,这样可以避免与CRUD的差异化。
五、注册与登录案例
1、注册
比如,在登录某网站前,是需要进行注册用户的。那么,注册是怎么做的呢?
其实,注册用户本质上就是给用户表添加一条数据。
例如,一起来完成:
(1)新建一个班级db_users数据库,编码为utf8;
(2)在库中新建一个用户表,字段有:编号id[主键自增]、用户名username、密码password;
(3)使用键盘录入数据的形式输入用户名、密码,并用于注册一个用户;
(4)使用DataGrip查看注册成功后的用户数据结果。
python
import pymysql
db_conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="db_users",
charset="utf8"
)
db_cursor = db_conn.cursor()
# 执行插入语句
in_name = input("请输入用户名:")
in_pwd = input("请输入密码:")
params = [in_name,in_pwd]
sql = "insert into tb_user(username,password) values(%s,%s)"
db_cursor.execute(sql,params)
# 提交事务
db_conn.commit()
db_cursor.close()
db_conn.close()
print("数据注册已结束!~~")
总结:
(1)当要注册用户时,本质上实现的是插入数据功能;
(2)注意:使用pymysql模块操作注册功能时,记得进行语句参数化。
2、登录
当成功注册用户信息后,则可以进行登录操作了。那么,登录是怎么做的呢?
其实,登录账户本质上就是:查询用户数据,并与用户手动输入的用户名和密码进行匹配。
当匹配成功,则可以登录;反之,则登录失败。
例如,一起来完成:
(1)使用键盘录入数据的形式输入用户名、密码,并用于登录操作;
(2)当登录时,使用的数据内容则是已注册成功的用户表信息;
(3)观察注册成功后的用户数据,当已匹配成功,则表示成功登录。
python
import pymysql
db_conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="db_users",
charset="utf8"
)
db_cursor = db_conn.cursor()
# 执行查询语句、匹配
sql = "select username,password from tb_user"
db_cursor.execute(sql)
query_result = db_cursor.fetchall()
print(query_result)
# 匹配
in_uname = input("请输入用户名:")
in_upwd = input("请输入密码:")
# for user in query_result:
for username,password in query_result:
if in_uname == username and in_upwd == password:
print(f"恭喜你,{username}, 已登录成功!!")
break # 跳出
else:
print("登录失败!!!")
# 提交事务
db_conn.commit()
db_cursor.close()
db_conn.close()
print("数据注册已结束!~~")
总结:
(1)在Python中,如果要判断数据内容是否匹配成功可以使用if语句
(2)注意:在实际应用中,登录和注册功能可能还会涉及到用户数据加密,比如MD5加密、SHA1加密等。