@(python)[笔记]
目录
一、数据库操作
1.1 数据库管理
1.1.1 显示
1.1.2 用户管理
1.1.3 授权管理
1.2 数据表操作
1.2.1 创建表
数据类型
修饰符
1.2.2 删除表
1.2.3 清空表
1.2.4 修改表
1.3 表内容操作
1.3.1 增
1.3.2 删
1.3.3 改
1.3.4 查
1.3.5 复杂查询
二、Python操作MySQL
2.1 下载安装
2.2 使用操作
2.2.1 执行查询操作
2.2.2 写库操作必须提交commit
2.2.3 直接获取新增数据的自增ID
2.2.4 将查询结果以字典形式返回
一、数据库操作
SQL语句分类:
SQL语句分为:
(1) DQL(数据查询语言):select
(2) DDL(数据定义语言):create/drop/alter/truncate
(3) DML(数据操纵语言):insert/update/delete
(4) TCL(事务控制语言):commit/rollback/savepoint
(5) DCL(数据控制语言):grant/revoke
1.1 数据库管理
1.1.1 显示
SHOW DATABASES
//显示所有数据库SHOW TABLES
//显示所有数据表USE db_name
//使用某个数据库
默认的数据库功能介绍
- mysql - 用户权限相关数据
- test - 用于用户测试数据
- information_schema - MySQL本身架构相关数据
1.1.2 用户管理
创建用户
create user '用户名'@'IP地址' identified by '密码';
删除用户
drop user '用户名'@'IP地址';
修改用户
rename user '用户名'@'IP地址'; to '新用户名'@'IP地址';;
修改密码
set password for '用户名'@'IP地址' = Password('新密码')
PS:用户权限相关数据保存在mysql数据库的user表中,所以也可以直接对其进行操作(不建议)
1.1.3 授权管理
show grants for '用户'@'IP地址'; -- 查看权限
grant 权限 on 数据库.表 to '用户'@'IP地址'; -- 授权
revoke 权限 on 数据库.表 from '用户'@'IP地址'; -- 取消权限
权限列表
权限名称 | 权限功能 |
---|---|
all privileges | 除grant外的所有权限 |
select | 仅查权限 |
select,insert | 查和插入权限 |
usage | 无访问权限 |
alter | 使用alter table |
alter routine | 使用alter procedure和drop procedure |
create | 使用create table |
create routine | 使用create procedure |
create temporary tables | 使用create temporary tables |
create user | 使用create user、drop user、rename user和revoke all privileges |
create view | 使用create view |
delete | 使用delete |
drop | 使用drop table |
execute | 使用call和存储过程 |
file | 使用select into outfile 和 load data infile |
grant option | 使用grant 和 revoke |
index | 使用index |
insert | 使用insert |
lock tables | 使用lock table |
process | 使用show full processlist |
select | 使用select |
show databases | 使用show databases |
show view | 使用show view |
update | 使用update |
reload | 使用flush |
shutdown | 使用mysqladmin shutdown(关闭MySQL) |
super | <dbff><dc42><dbff><dc08>使用change master、kill、logs、purge、master和set global。还>允许mysqladmin<dbff><dd57><dbff><dd58><dbff><dc8a><dbff><dc8b>调试登陆 |
replication client | 服务器位置的访问 |
replication slave | 由复制从属使用 |
对于数据库
对于目标数据库以及内部其他:
数据库表示 | 说明 |
---|---|
数据库名.* | 数据库中的所有 |
数据库名.表 | 指定数据库中的某张表 |
数据库名.存储过程 | 指定数据库中的存储过程 |
*.* | 所有数据库 |
对于用户和IP地址
表示方法 | 说明 |
---|---|
用户名@IP地址 | 用户只能在改IP下才能访问 |
用户名@192.168.1.% | 用户只能在改IP段下才能访问(通配符%表示任意) |
用户名@% | 用户可以再任意IP下访问(默认IP地址为%) |
刷新权限列表
flush privileges
//将数据读取到内存中,从而立即生效
root忘记密码解决办法
# 启动免授权服务端
mysqld --skip-grant-tables
# 客户端
mysql -u root -p
# 修改用户名密码
update mysql.user set authentication_string=password('666') where user='root';
#刷新权限列表
flush privileges;
1.2 数据表操作
1.2.1 创建表
create table 表名(
列名 类型 是否可以为空,
列名 类型 是否可以为空
)ENGINE=InnoDB DEFAULT CHARSET=utf8
数据类型
1. 数值类型
数值类型 | 字节 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
TINYINT 整数 | 1字节 | (-128,127) | (0,255) | 小整数值 |
SMALLINT 整数 | 2字节 | (-32 768,32 767) | (0,65 535) | 大整数值 |
MEDIUMINT 整数 | 3字节 | (-8 388 608,8 388 607) | (0,16 777 215) | 大整数值 |
INT或INTEGER 整数 | 4字节 | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整数值 |
BIGINT 整数 | 8字节 | (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 极大整数值 |
FLOAT 浮点数 | 4字节 | (-3.402 823 466 E+38,1.175 494 351 E-38) | (0,3.402 823 466 351 E+38) | 单精度浮点数值 |
DOUBLE 浮点数 | 8字节 | (1.797 693 134 862 315 7 E+308,2.225 073 858 507 201 4 E-308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度浮点数值 |
DECIMAL 浮点数 | 未知 | 未知 | 未知 | 绝对精度 |
2. 字符串类型
字符串类型 | 字节大小 | 描述及存储需求 |
---|---|---|
CHAR | 0-255字节 | 定长字符串 |
VARCHAR | 0-255字节 | 变长字符串 |
TINYBLOB | 0-255字节 | 不超过 255 个字符的二进制字符串 |
TINYTEXT | 0-255字节 | 短文本字符串 |
BLOB | 0-65535字节 | 二进制形式的长文本数据 |
TEXT | 0-65535字节 | 长文本数据 |
MEDIUMBLOB | 0-16 777 215字节 | 二进制形式的中等长度文本数据 |
MEDIUMTEXT | 0-16 777 215字节 | 中等长度文本数据 |
LOGNGBLOB | 0-4 294 967 295字节 | 二进制形式的极大文本数据 |
LONGTEXT | 0-4 294 967 295字节 | 极大文本数据 |
VARBINARY(M) | 允许长度0-M个字节的定长字节符串,值的长度+1个字节 | |
BINARY(M) | 允许长度0-M个字节的定长字节符串 |
3. 日期和时间类型
类型 | 大小(字节) | 范围 | 格式 | 用途 |
---|---|---|---|---|
DATE | 4 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2037 年某时 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
4. ENUM枚举类型
ENUM 类型因为只允许在集合中取得一个值,有点类似于单选项。在处理相互排拆的数据时容易让人理解,比如人类的性别。ENUM 类型字段可以从集合中取得一个值或使用 null 值。
5. SET 集合类型
SET 类型与 ENUM 类型相似但不相同。SET 类型可以从预定义的集合中取得任意数量的值。并且与 ENUM 类型相同的是任何试图在 SET 类型字段中插入非预定义的值都会使
MySQL 插入一个空字符串。如果插入一个即有合法的元素又有非法的元素的记录,MySQL 将会保留合法的元素,除去非法的元素。
修饰符
- NOT NULL / NULL 表示是否可为空
- **DEFAULT Null ** 表示默认值为Null
- auto_increment ** 表示自增,注意:**1.每个表只允许有一列为自增列;2. 对于自增列,必须是索引(含主键);3. 对于自增,可以设置步长和起始值。
- primary key 表示设为主键,注意:主键,是一种特殊的唯一索引,不允许有空值,如果主键使用单个列,则它的值必须唯一,如果是多列,则其组合必须是唯一。
- 设置外键:constraint fk_name foreign key 字段名 references 外表名(字段名),加粗字体为关键字,fk_name为自定义的外键名。
- UNSIGNED 修饰符规定字段只保存正值。
1.2.2 删除表
drop table 表名
1.2.3 清空表
delete from 表名 //不会清空自增ID
truncate table 表名 //会将自增ID也清空
1.2.4 修改表
添加列:alter table 表名 add 列名 类型
删除列:alter table 表名 drop column 列名
修改列:
alter table 表名 modify column 列名 类型; -- 类型
alter table 表名 change 原列名 新列名 类型; -- 列名,类型
添加主键:
alter table 表名 add primary key(列名);
删除主键:
alter table 表名 drop primary key;
alter table 表名 modify 列名 int, drop primary key;
添加外键:alter table 从表 add constraint 外键名称(形如:FK_从表_主表) foreign key 从表(外键字段) references 主表(主键字段);
删除外键:alter table 表名 drop foreign key 外键名称
修改默认值:ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000;
删除默认值:ALTER TABLE testalter_tbl ALTER i DROP DEFAULT;
1.3 表内容操作
1.3.1 增
insert into 表 (列名,列名...) values (值,值,值...)
insert into 表 (列名,列名...) values (值,值,值...),(值,值,值...) //一次插入多行
insert into 表 (列名,列名...) select (列名,列名...) from 表 //插入的值是从其它表查询到的结果
1.3.2 删
delete from 表 //清空表内容
delete from 表 where id=1 and name='alex' //根据指定条件删除对应的行
1.3.3 改
update 表 set name = 'alex' where id>1
1.3.4 查
查询语法:
SELECT *|field1,filed2 ... FROM tab_name
WHERE 条件
GROUP BY field
HAVING 筛选
ORDER BY field
LIMIT 限制条数
Mysql在执行sql语句时的执行顺序:
-- from where select group by having order by
select * from 表
select * from 表 where id > 1
select nid,name,gender as gg from 表 where id > 1
select distinct gender from student; //distinct 可以让相同的值只出现一次
1.3.5 复杂查询
a、条件
select * from 表 where id > 1 and name != 'alex' and num = 12;
select * from 表 where id between 5 and 16;
select * from 表 where id in (11,22,33)
select * from 表 where id not in (11,22,33)
select * from 表 where id in (select nid from 表)
b、通配符
select * from 表 where name like 'ale%' - ale开头的所有(多个字符串)
select * from 表 where name like 'ale_' - ale开头的所有(一个字符)
c、限制
select * from 表 limit 5; - 前5行
select * from 表 limit 4,5; - 从第4行开始的5行
select * from 表 limit 5 offset 4 - 从第4行开始的5行
注意:跟NULL作比较时,不能使用=等于号,要用 is
d、排序
select * from 表 order by 列 asc - 根据 “列” 从小到大排列
select * from 表 order by 列 desc - 根据 “列” 从大到小排列
select * from 表 order by 列1 desc,列2 asc - 根据 “列1” 从大到小排列,如果相同则按列2从小到大排序
e、分组
select num from 表 group by num
select num,nid from 表 group by num,nid
select num,nid from 表 where nid > 10 group by num,nid order nid desc
select num,nid,count(*),sum(score),max(score),min(score) from 表 group by num,nid
select num from 表 group by num having max(id) > 10
计算男生和女生的平均年龄:
select avg(age) from student group by gender;
注意:特别的:group by 必须在where之后,order by之前。having 后跟过滤条件,只能跟group by 一起用,用于将group by分组后的结果再次过滤;分组的主要目的就是做聚合计算的。
- sum() 求和
- min() 求最小值
- max() 求最大值
- avg() 求平均值
- count() 求次数
- count()* 统计符合条件的记录条数
聚合函数的括号中填一个列名,例如:sum(number)表示计算number这一列数值的和。
f、连表
无对应关系则不显示
select A.num, A.name, B.name
from A,B
Where A.nid = B.nid
无对应关系则不显示
select A.num, A.name, B.name
from A inner join B
on A.nid = B.nid
A表所有显示,如果B中无对应关系,则值为null
select A.num, A.name, B.name
from A left join B
on A.nid = B.nid
B表所有显示,如果B中无对应关系,则值为null
select A.num, A.name, B.name
from A right join B
on A.nid = B.nid
g、组合
组合,自动处理重合
select nickname
from A
union
select name
from B
组合,不处理重合
select nickname
from A
union all
select name
from B
h、正则表达式过滤
REGEXP或者RLIKE
支持正则表达式过滤
select * from 表 where name like '^ale' //查找name是以ale开头的行
二、Python操作MySQL
在Python中操作MySQL用pymysql
模块,其使用方法和MySQLdb
几乎相同。
2.1 下载安装
pip3 install pymysql
2.2 使用操作
2.2.1 执行查询操作
import pymysql
# 创建连接
conn = pymysql.Connect(host="127.0.0.1",
port=3306,
user="root",
password="123456",
database="study",
charset="utf8")
# 创建游标,利用游标支数据库取数据
cursor = conn.cursor()
#执行SQL,返回值v是受影响的行数
v = cursor.execute('select * from student')
result = cursor.fetchall() #获取返回的全部数据,元组形式
# result = cursor.fetchone() #获取返回的第1条数据
# result = cursor.fetchmany(2) #获取返回的指定行数的数据,不指定行数,默认只获取一行数据,返回元组形式
print(result)
#关闭游标
cursor.close()
#关闭连接
conn.close()
注意:
fetchone()
有一个数据指针,获取一行,就会跳到下一行,不能返回。
实例:读取数据库,验证用户登录
#通过读数据库验证用户登录
import pymysql
username = input("请输入用户名:")
password = input("请输入密码:")
try:
# 创建连接
conn = pymysql.Connect(host="127.0.0.1",
port=3306,
user="root",
password="123456",
database="study",
charset="utf8")
# 创建游标,利用游标支数据库取数据
cursor = conn.cursor()
sql = 'select * from userinfo where username="%s" and password="%s" '%(username,password)
cursor.execute(sql)
result = cursor.fetchall() #获取返回的全部数据,元组形式
if result:
print("登录成功")
else:
print("账号或密码错误")
except Exception as e:
print(e)
raise
finally:
cursor.close()
conn.close()
注意:以上代码有SQL注入的漏洞,请看如下演示
演示一:输入正确用户名和密码
演示二: 输入用户名:alex" -- , 输入任意密码
解析:由上图可以看出,用户名和密码都是错误的,也可以通过验证。这是为什么呢?我们来解析一下通过用户名和密码生成的SQL。通过字符串替换,我们可以得到这样一条SQL:
select * from userinfo where username="alex" -- " and password="sdfsfsd"
。从这条SQL可以看出,username="alex"
后面被--
注释了(--
是SQL语言中的注释符),后面的语句就不能被mysql解析了,所以不管密码输入的是什么,都会被忽略掉。
演示三:输入用户名:xxx" or 1=1 -- , 输入任意密码
解析:由上图可以看出,即使不知道数据库中的用户名和密码是什么,也可以通过验证。通过字符串替换,我们得到这样的一条SQL:
select * from userinfo where username="xxx" or 1=1 -- " and password="asdffas"
。这条SQL,1=1
后面被注释了,而select * from userinfo where username="xxx" or 1=1
是永远成立的,可以从数据库获取到值,所以可以通过验证。
改进版《读取数据库,验证用户登录》
防止被SQL注入
我们在输入SQL字符串时,不要自己去做字符串格式化替换,可以在给execute
方法传参时,第一个参数传查询的SQL,第二个参数传SQL中要替换的字符串列表。pymysql模块内部会自动替换,在替换时,会将特殊字符替换掉。
#改进版
import pymysql
username = input("请输入用户名:")
password = input("请输入密码:")
try:
# 创建连接
conn = pymysql.Connect(host="127.0.0.1",
port=3306,
user="root",
password="123456",
database="study",
charset="utf8")
# 创建游标,利用游标支数据库取数据
cursor = conn.cursor()
sql = 'select * from userinfo where username=%s and password=%s '
cursor.execute(sql,[username,password]) #第2个参数为列表
result = cursor.fetchall() #获取返回的全部数据,元组形式
if result:
print("登录成功")
else:
print("账号或密码错误")
except Exception as e:
print(e)
raise
finally:
cursor.close()
conn.close()
演示四:
可以看出,代码改进后,就不会再出现被SQL注入了。
2.2.2 写库操作必须提交commit
对数据库进行增、删、改操作都必须执行提交(commit)操作
import pymysql
# 创建连接
conn = pymysql.Connect(host="127.0.0.1",
port=3306,
user="root",
password="123456",
database="study",
charset="utf8")
cursor = conn.cursor()
#执行SQL,返回值v是受影响的行数
sql = 'insert into userinfo(username,password) values(%s,%s)'
cursor.execute(sql,["eric","123321"])
#对数据库进行增、删、改操作都必须执行提交(commit)操作
conn.commit()
cursor.close()
conn.close()
2.2.3 直接获取新增数据的自增ID
cursor.lastrowid
方法可以直接获取新增数据的自增ID
需求:现在我想往class班级表中新插入一个班级,然后再往这个新班级中插入一条学生数据(包含班级ID)。
import pymysql
# 创建连接
conn = pymysql.Connect(host="127.0.0.1",
port=3306,
user="root",
password="123456",
database="study",
charset="utf8")
cursor = conn.cursor()
cursor.execute('insert into class(caption) values("三年三班")')
new_class_id = cursor.lastrowid #获取新增数据的自增ID
cursor.execute('insert into student(sname,gender,class_id) values(%s,%s,%s)',["李杰","女",new_class_id])
#对数据库进行增、删、改操作都必须执行提交(commit)操作
conn.commit()
cursor.close()
conn.close()
2.2.4 将查询结果以字典形式返回
需要在conn.cursor()
传一个参数:conn.cursor(cursor=pymysql.cursors.DictCursor)
import pymysql
conn = pymysql.Connect(host="127.0.0.1",
port=3306,
user="root",
password="123456",
database="study",
charset="utf8")
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select * from class")
result = cursor.fetchall()
print(result)
cursor.close()
conn.close()
'''
输出结果:
[{'cid': 1, 'caption': '三年二班'}, {'cid': 2, 'caption': '一年三班'}, {'cid': 3, 'caption': '三年一班'}, {'cid'
'''