目录
一、正则表达式的概述
1、基本介绍
2、快速使用re模块
二、正则的常见规则
1、匹配单个字符
2、原始字符串
3、匹配多个字符
4、匹配开头和结尾
5、匹配分组
三、Python与MySQL交互
1、pymysql模块的安装
2、pymysql的操作步骤
3、connection对象
4、cursor对象
四、数据记录操作
1、准备数据表
2、插入数据
3、修改数据
4、删除数据
5、SQL注入
6、语句参数化
7、查询数据
五、注册与登录案例
1、注册
2、登录
一、正则表达式的概述
1、基本介绍
正则表达式,也叫做规则表达式,通常会说成【正则】。
实际上,正则表达式就是指符合一定规则的字符串,同时它能用于检查一段文本数据是否与某种模式匹配。
比如,在网站注册新用户时,对用户名、手机号等的验证就使用了正则表达式。
在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模块完成对手机号码的验证。
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来匹配一个可能有数字、大小写字母、下划线的单个字符。
# 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,语法:
r"正则表达式"
例如,一起来完成:
(1)请使用正则来匹配路径名:E:\\
;
(2)请尝试使用不同方式去匹配数据,观察效果;
(3)思考:当要定义一段批量文本内容时,该怎么定义字符串?
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位的密码,可以是大小写英文字母、数字、下划线。
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的结尾处。
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等。
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模块前,先进行安装:
pip install pymysql
有时使用pip install xxx命令安装时较慢,若要提升pip下载的速度,可采用命令:
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模块后,可直接导入使用:
# 导入模块
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)对各个步骤做详细说明。
(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)操作完成后,查看表结构,并查看表内是否有数据内容。
######################新建库和表#############################
# 创建库
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)思考:如果要插入两条数据,该怎么做呢?
# 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呢?
# 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()操作数据时,都采用硬编码方式,会存在什么问题吗?
# 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注入问题呢?
# 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()函数中的格式化符号输出:
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查看添加成功后的数据结果。
# 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()
# 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()查询出所有数据信息,并遍历出详细信息。
# 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查看注册成功后的用户数据结果。
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)观察注册成功后的用户数据,当已匹配成功,则表示成功登录。
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加密等。