字符编码和配置文件
一、前提
\s:查看数据库基本信息
my-default.ini:Windows下MySQL默认的配置文件
拷贝上述文件并重命名为my.ini
由于5.6版本编码不统一,会造成乱码,我们需要统一修改>>>:utf8
二、添加字符编码相关配置
[mysqld]
character-set-server=utf8
collection-server=utf8_general_ci
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
如果配置文件涉及到了mysqld相关的配置修改,那么需要重启服务端才可以生效
ps:在配置文件中mysql下提前写好用户名和密码,之后mysql直接登录
存储引擎
一、介绍
可以简单地理解存储引擎为:针对相同数据采用的不同的存储策略
查看所有的存储引擎:show engines
二、需要掌握的存储引擎
1.MyISAM
MySQL5.5及之前版本默认的存储引擎
2.InnoDB
MySQL5.5之后版本默认的存储引擎
存取数据的速度没有MyISAM快,但是支持事物、行锁、外检等诸多功能,安全性比较高
3.Memory
基于内存的存储引擎,存取数据极快,但是断电立刻丢失
4.BlackHole
黑洞,任何写进去的数据都会立刻丢失,类似于垃圾站
三、不同存储引擎之间底层文件的区别
MySQL中默认大小写不敏感(忽略大小写)
creat table t1(id int) engine=innodb;
craet table t2(id int) engine=myisam;
creat table t3(id int) engine=memory;
creat table t4(id int) engine=blackhole;
ps:windows cmd终端鼠标右键的意思就是粘贴
InnoDB
.frm 表结构
.ibd 表数据、表索引(加快数据查询)
MyISAM
.frm 表结构
.MYD 表数据
.MYI 表索引(加快数据查询)
Memory
.frm 表结构
BlackHole
.frm 表结构
insert into t1 values(1);
insert into t2 values(1);
insert into t3 values(1);
insert into t4 values(1);
创建表的完整语法
creat table 表名 (
字段名1 字典类型(数字) 约束条件,
字段名2 字典类型(数字) 约束条件,
字段名3 字典类型(数字) 约束条件,
)
1.字段名和字段类型是必须的(至少一个)
2.数字跟约束条件是可选的(可有可无)
3.约束条件可以写多个,空格隔开即可
4.最后一个字段的结尾千万不能加逗号
字段类型之整型
类型 | 大小 | 有负号 | 没负号 |
---|---|---|---|
tinyini | 1bytes | -128~127 | 0~255 |
smallinit | 2bytes | ||
int | 4bytes | ||
bigint | 8bytes |
一、验证整型是否自带符号
creat table t6(id tinyint);
insert into t6 values(-129),(256);
# 发现字段填写为两个边界值,数据失真,没有实际意义
'''上述所有的整型类型默认都会自带负号'''
二、自定义移除负号
1.unsigned
'''unsigned 约束条件之一,意思是不需要负号'''
create table t7(id tinyint unsigned);
insert into t7 values(-129),(256);
2.温馨提示
插入的数据值超出了数据类型的范围,不应该让其插入并自动修改,没有意义
数据库应该直接报错,但是被我们在配置文件里修改了
3.修改
方式一:命令临时修改
当前客户端操作界面有效:
set session sql_mode = 'strict_trans_tables'
服务端不重启永远有效:
set golbal sql_mode='STRICT_TA\RANS_TABLES'
方法二:配置文件永久修改
[mysqld]
sql_mode='STRICT_TRANS_TABLES'
字段类型之浮点型
一、float double decimal 都可以存储浮点型数据,但是各自精确度不一致
二、使用方式
float(255,30)
double(255,30)
decimal(65,30)
# 第一个数表示总共多少位,第二个数表示小数占多少位
三、验证精确度问题
# 创建表
creat table t8(id float(255,30));
creat table t9(id double(255,30));
creat table t10(id decimal(65,30));
# 添加数据
insert into t8
values(1.11111111111111111111111111111);
insert into t9 values(1.11111111111111111111111111111);
insert into t10 values(1.11111111111111111111111111111);
float < doublel < decimal
'''
一般情况下float就够用了
如果想要追求完美的精确度,可以使用字符串来代替
'''
字段类型之字符类型
一、char 特点:定长(例:char(4))
1.括号里是4,最大就只能储存4个字符,如果超出范围直接报错
2.如果不超出范围,则用空格填充至最大范围4
二、varchar 特点:可变长(例:varchar(4))
1.括号里是4,最大就只能储存4个字符,如果超出范围直接报错
2.如果不超出范围,则有几位就几位
三、验证两者的区别
creat table t11(id int,name char(4));
creat table t12(id int,name varchar(4));
1.结果验证超出范围两者都会报错
注意!!
sql_mode='strict_trans_tables'
2.验证定长和变长特性
char_length() # 统计字段数据的长度
3.两者对比
char:
整存整取,速度快
浪费存储空间
varchar:
节省存储空间
存取数据的速度比char慢
"""
char(4)
a son jacktom lili
varchar(4)
1bytes+a1bytes+son1bytes+jack1bytes+tom1bytes+lili
存取数据都需要操作报头(耗时)
存储人的姓名>>>:varchar
"""
4.两者使用频率都很高,现在默认很多时候是varchar
默认情况下char在存储的时候针对没有满足固定位数的字符会自动填充空格
然后在读取的时候又会自动将填充的空格移除,如果想要取消该机制,需要sql_mode
set global
sql_mode='strict_trans_tables,pad_char_to_full_length';
# 上述目录是替换,不是新增,所以在配置文件里也要写上
数字的含义
一、特殊
数字大部分情况下都是用来限制字段的存储长度,但是整型除外!
在整型:不是用来限制存储的长度,而是展示的长度
craet table t13(id int(3));
creat table t14(id int(3) zerofill);
二、总结
以后涉及到整型字段的定义,类型后面不需要加括号写数字,除非业务有需求必须固定位数
eg:00000013 00123023
字段类型之枚举与集合
一、枚举
多选一,例:性别(男 ,女,其他)
creat table t15(
id int,
name varchar(32),
gender enum('male','female','others')
);
二、集合
多选多(包含多选一),例:爱好(唱,跳,rap)
creat table t16(
id int,
name varchar(32),
hobbies set('sing','dance','rap')
)
字段类型之日期类型
类型 | 含义 |
---|---|
data | 年月日 |
datatime | 年月日时分秒 |
time | 时分秒 |
year | 年份 |
creat table t17(
id int,
name varchar(32),
birth date,
reg_time time,
study_time time,
join_time year
);
insert into t17 values(1,'jason','2022-11-11','2000-11-11 11:11:11','11:11:11','1995');
字段约束条件
'''
默认按照创建表的字段顺序添加
insert into 表名 values()
可以自定义字段顺序
insert into 表名(字段) values()
'''
1.unsigned 无负号
id int unsigned
2.zerofill 零填充
id int zerofill
3.not null 非空
name varchar(32) not null
4.default 默认值
name varchar(32) default 'jason'
5.unique 唯一值
id int unique 单列唯一
host varchar(32)
port int
unque(host,port) # 联合唯一
约束条件
一、primary key主键
1.单从约束角度上而言主键等价于非空且唯一 (= not null unique)
create table t1(
id int primary key,
name varchar(32)
);
2.InnoDB存储引擎规定一张表必须要有且只有一个主键
2.1.如果创建的表中没有主键也没有非空且唯一的字段,nameInnoDB存储引擎会自动采用一个隐藏的字段作为主键(主键可以加快数据的查询:比如新华字典的目录)
2.2.如果创建的表中没有主键也没有非空且唯一的字段,那么InnoDB存储引擎会自动将该字段设置为主键
create table t2(
nid int not null unique,
sid int not null unique,
uid int not null unique,
name varchar(32)
);
3.创建表的时候都应该有一个‘id’字段,并且该字段应该作为主键
uid、sid、pid、gid、cid、id
补充说明:
id int primary key 单列主键
sid int,
nid int,
primary key(sid,nid) 联合主键
二、auto_increment自增
1.介绍
该约束条件不能单独使用,必须跟在键后面(主要配合主键一起使用)
create table t3(
id int auto_increment
);
there can be only one auto column and it must be defind as a key
create table t3(
id int primary key auto_increment,
name varchar(32)
);
2.补充说明:自增的特点
自增的操作不会因为执行删除数据的操作而退回或者重置
delete from
如果非要重置主键,需要格式化表
truncate 表名;
# 删除表数据并重置主键
三、foreign key 外键
1.外键前戏
1.1.需要创建一张员工表,有以下内容:
id 、name、gender、dep_name、dep_desc
1.2.上述表的缺陷
表结构不清晰,到底是员工表还是部门表
字段数据反复存取,浪费存储空间
表的扩展性差,牵一发动全身,效率极低
1.3.优化操作 >>>: 拆表
员工表:id 、name、gender
部门表:id 、dep_name、dep_desc
# 拆表之后解决了上述三个问题,但是出现了一个致命问题,两张表,不能够互相设为外键
'''解决措施:另建一张表'''
id name gender dep_id
添加一个部门编号字段填写部门数据的主键值
外键字段:专门用于记录表与表之间数据的关系
2.介绍
外键字段使用来记录表与表之间数据的关系,而数据的关系有四种:
一对多关系、多对多关系、一对一关系、没有关系
四、表与表之间的关系
1.表数据关系的判定方法 >>>:'换位思考'
2.一对多关系
2.1.以员工表和部门表为例
1.站在员工表的角度
问:一条员工数据能否对应多条部门数据?
== 一名员工是否能隶属于多个部门?
答:不可以
2.站在部门表的角度
问:一个部门数据能否对应多条员工数据?
== 一个部门是否可以拥有多个员工?
答:可以
换位思考之后得出的答案,一个可以一个不可以
那么表的关系就是:'一对多'
部门是一,员工是多
针对'一对多'的关系,外键字段建在多的一方
2.2.代码演示
1.先写普通字段
2.再写外键字段
create table emp(
id int primary key auto_increment,
name varchar(32),
gender enum('male','female','otherrs') default 'male',
dep_id int,
forgin key(dep_id) references dep(id)
);
creat table dep(
id int primary key auto_increment,
dep_name varchar(32),
dep_desc varchar(32)
);
'''
1.创建表的时候需要先创建被关联的表(没有外键),然后是关联表(有外键)
2.出入表数据的时候,针对外键字段只能是填写被关联表字段已经出现过的数据值
3.被关联字段无法修改和删除,操作限制性太强,有点不太好
'''
"""
级联更新、级联删除:
被关联对象一旦变动,滚立案的数据同步变动
"""
create table emp1(
id int primary key auton_increment,
name varchar(32),
gender enum('male','female','others') default 'male',
dep_id int,
foreigin key(dep_id) references dep(id)
on update cascade # 级联更新
on delete cascade # 级联删除
);
creat table dep1(
id int primary key auto_increment,
dep_name varchar(32),
dep_desc varchar(32)
);
'''
扩展:
在实际工作中,很多时候可能不会使用外键
因为外键增加了表之间的耦合性,不便于单独操作,资源消耗增加
我们为了能够描述出表数据之间的关系,又不想使用外键
我们可以通过写SQL,建立代码层面的关系
'''
3.多对多关系
3.1.以书籍表和作者表为例
1.站在书籍表的角度
问:一条书籍数据能否对应多条作者表数据?
== 一本书是否可以有多个作者?
答:可以
2.站在作者表的角度
问:一条作者数据是否能对应多条书籍表数据?
== 一个作者是否可以有多本书?
答:可以
总结:两边都可以对应多条数据,name表数据关系就是'多对多'
针对'多对多'关系,外键字段不能健在任意一方!!!
3.2.代码演示
create table book(
id int primary key auto_increment,
title varchar(32),
author_id int,
foreign key(author_id) references author(id)
on update cascade # 级联更新
on delete cascade # 级联删除
);
create table author(
id int primary key auto_increment,
name varchar(32),
book_id int,
foregin key(book_id) references book(id)
on update cascade # 级联更新
on delete cascade # 级联删除
);
'''需要单独开设第三张表来存储数据关系'''
create table book(
id int primary key suto_increment,
title varchar(32)
);
creat table author(
id int primary key auto_increment,
name varvchar(32)
);
create table book2author(
id int primary key auto_increment,
book_id int,
foreign key(book_id) references book(id)
on update cascade
on delete cascade,
author_id int,
foreign key(author_id) references author(id)
on update cascade
on delete cascade
);
4.一对一关系
4.1.以用户表和用户详情表为例
1.站在用户表角度
问:一条用户表数据能否对应多条用户详情表数据?
== 一个用户是否有多个用户详情?
答:不可以
2.站在用户详情表角度
问:一条用户详情表数据能否对应多条用户表数据?
== 一个用户详情是否能是多个用户的?
答:不可以
总结:两边都不可以,先考虑是不是没有关系
如果有关系那就是'一对一'
针对'一对一'关系的表,外键字段建在任何一张表都可以
但是建议建在查询频率比较高的表,便于后期查询
4.2.代码演示
create table user(
id int perimary ket auto_increment,
name varchar(32),
detail_id int unique,
foreign key(detail_id) references userDetail(id)
on update cascade
on delete cascade
);
create table userDetail(
id int primary key auto_increment,
phone bigint
);
操作标的SQL语句
1.修改表名
alter table 表名 rename 新表名;
2.新增字段
alter table 表名 add 字段名 字段类型(数字) 约束条件;
alter table 表名 add 字段名 字段类型(数字) 约束条件 after 已经存在的字段; # 在某个字段后面添加字段
alter table 表名 add 字段名 字段类型(数字) 约束条件 first; # 添加在最前面
3.修改字段
alter table 表名 change 旧字段名 新字段名 字段类型(数字) 约束条件; # 修改字段名、字段类型
alter table 表名 modify 字段名 新的字段类型(数字) 约束条件; # 只能修改字段类型
4.删除字段
alter table 表名 drop 字段名;
表查询关键字
一、数据准备
create table emp(
id int not null unique auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, #一个部门一个屋子
depart_id int
);
#三个部门:教学,销售,运营
insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values
('jason','male',18,'20170301','浦东第一帅形象代言',7300.33,401,1), #以下是教学部
('tom','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('tony','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jack','female',18,'20110211','teacher',9000,401,1),
('jenny','male',18,'19000301','teacher',30000,401,1),
('sank','male',48,'20101111','teacher',10000,401,1),
('哈哈','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
('呵呵','female',38,'20101101','sale',2000.35,402,2),
('西西','female',18,'20110312','sale',1000.37,402,2),
('乐乐','female',18,'20160513','sale',3000.29,402,2),
('拉拉','female',28,'20170127','sale',4000.33,402,2),
('僧龙','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3);
二、select 与 from
1.SQL语句的关键字编写顺序与执行数据是不一致的!!
eg:
select name from emp;
肯定是线支持from确定表,之后执行select确定字段
2.编写SQL语句针对select和from可以先写个固定模板
select * from 表名 其他操作;
# select后的字段可能是实际的,也可能是通过SQL动态产生的,所以可以先用*占位最后再修改
select
自定义查询表中字段对应的数据
from
指定操作的对象(到底是哪张表,也可能多张表)
三、where筛选
1.查询id大于等于3小于等于6的数据
select * from emp where id>=3 and id<6;
2.查询薪资是20000或者18000或者17000的数据
# 方法一
select * from emp where salary=20000 or salary=18000 or salary=17000;
# 方法二
select * from emp where salary in (20000,18000,17000);
3.查询员工姓名中包含o字母的员工姓名和薪资
select * from emp where name like '%o%';
# %想要筛选的字符串&
4.查询员工姓名是由四个字符组成的员工姓名与其薪资
select * from emp where name like '_o%'; # o前面只有一个字符
# _控制字符位数
select * from emp where name like'____';
# 查找name是四位字符的数据
5.查询id小于3或者大于6的数据
select * from emp where id<3 or id>6;
6.查询薪资不在20000,18000,17000范围的数据
select * from emp where salary not in (20000,18000,17000);
7.查询岗位描述为空的员工名与岗位名
select * from emp where post is null;
# 针对判断是否为null要用 is
三、group by 分组
1.介绍
分组:按照一些指定的条件将单个数据分为一个个整体
分组之后我们研究的对象应该是以组为单位不应该再直接获取单个数据项,如果获取了应该直接报错,5.6.44版本低的缺陷,需要自己设置
set global sql_mode = 'strict_trans_tables,only_full_group_by';
select后面可以直接填写的字段名只能是分组的依据(其他字段需要借助一些方法才可以获取)
2.写SQL时是否需要分组,根据需求分析
比如求最大、最小、总和、平均
分配组合常见的有聚合函数
最大值:max
最小值:min
总和:sum
计数:count
平均:avg
3.以组为单位统计组内数据
以组为单位统计组内数据>>>聚合查询(聚集到一起合成为一个结果)
3.1.每个部门的最高工资 max
select post,max(salary) from emp group by post;
# 用as取别名
select post as '部门',max(salary) as '薪资' from emp group by post;
3.2.每个部门的最低工资 min
select post,min(salary) from emp group by post;
# 可以综合使用,更精准的查找数据
select post,min(salary) from emp where post is not null group by post; # 排除post是null的数据
3.3.每个部门的平均工资 avg
select post as '部门',avg(salary) as '平均薪资' from emp group by post;
# as取别名
3.4.每个部门的工资总和 sum
select post as '部门',sum(salary) as '总薪资' from emp group by post;
3.5.每个部门的人数 count计数
select post as '部门',count(id) as '总人数' from emp group by post;
3.6.分组之后的每个部门名称和每个部门下的员工姓名 group_concat(字段名)
select post,group_concat(name) from emp group by post;
# group_concat(字段名) 分组之后用,不仅可以用来显示除分组外的字段,还可以拼接字符串
select post,group_concat(name,'|',post) from emp group by post;
select post,group_concat(name,'|','666') from emp group by post;
四、having 过滤
1.介绍
where和having的功能其实是一样的,都是用来筛选数据
只不过where用于分组之前的筛选,而having用于分组之后的筛选
为了人为的区分,所以叫where是筛选,having是过滤
2.统计各部门年龄大于30岁的员工的平均薪资,并保留平均工资大于10000的部门
select post,avg(salary) from emp
where
age>30
group by post
having avg(salary) > 10000;
五、distinct 去重
1.前提:数据必须一模一样
select distinct age from emp;
六、older by 排序
1.升序
select * from emp order by salary; # 默认升序
# 也可以用asc设定
select * from emp order by salary asc; # 升序
2.降序
select * from emp order by salary desc; # 降序
3.先按照age降序排,在年龄相同的情况下再按照薪资升序排
select * from emp order by age desc,salary asc;
4.统计各部门年龄在10岁以上的员工平均薪资,并且保留平均薪资大于3000的部门,然后对平均工资进行排序
select post as '部门',avg(salary) from emp
where age >10 # 筛选年龄大于10
group by post # 按部门分组
having avg(salary) > 3000 # 过滤平均薪资小于3000
order by avg(salary); # 按平均薪资升序排列
七、limit 分页
1.限制展示条数
select * from emp limit 3;
# 限制展示3条记录
2.查询工资最高的人的详细信息
select * from emp order by salary # 按薪资升序排列
limit 1; # 限制展示一条
3.分页展示
select *from emp limit 0,5;
# 展示 1~5 5条记录(不包含0)
select * from emp limit 5,5;
# 展示 6~10 5条记录(不包含5)
'''
第一个参数:表示起始位置
第二个参数:表示展示数量
'''
八、regexp 正则
1.正则表达式回顾
1.1.不同字符组的意义
在没有量词修饰的情况下,一次只会针对一个数据值
字符组 | 意义 |
---|---|
[0-9] | 0~9任意数字 |
[A-Z] | A~Z任意字母 |
[a-z] | a~z任意字母 |
[0-9a-zA-Z] | 任意数字、大写字母或小写字母 |
1.2.特殊符号
在没有量词修饰的情况下,一个符号一次只会针对一个数据值
特殊符号 | 意义 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母、数字或下划线 |
\W | 匹配非(字母、数字或下划线)的任意字符 |
\d | 匹配数字 |
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
^...$ | 精确匹配具体数值,只能匹配^和$质按进度数据值 |
a|b | 匹配字符a或b |
() | 给正则表达式分组 |
[] | 匹配[ ]内的所有字符 |
[^] | 匹配除了[ ]内的所有字符 |
1.3.量词
不能单独使用,必须跟在表达式后面,只能影响紧挨着的左边那个,默认贪婪匹配
量词 | 意义 |
---|---|
* | 重复零次或多次 |
+ | 重复一次或多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 至少重复n次 |
{n,m} | 重复n到m次 |
2.实践使用regexp
# 查询name是j开头,n或y结尾的数据
select * from emp where name regexp '^j.*(n|y)$';
多表查询
一、多表查询思路
1.子查询
将一张表的查询结果括号括起来当做另外一条SQL语句的条件
eg:类似于日常生活中解决问题的方式
第一步做……
第二步基于第一步的结果做……
2.连表操作
先将所有涉及到结果的表全部都拼接到一起,形成一张大表,然后从大表中查询数据
3.代码演示
# 1.建表
create table dep1(
-> id int primary key auto_increment,
-> name varchar(32));
create table emp1(
-> id int primary key auto_increment,
-> name varchar(32),
-> gender enum('male','female')not null default 'male',
-> age int,
-> dep_id int);
# 2.添加数据
insert into dep1 values
-> (200,'技术'),
-> (201,'人力资源'),
-> (202,'销售'),
-> (203,'运营'),
-> (204,'安保');
insert into emp1(name,gender,age,dep_id)values
-> ('jason','male',18,200),
-> ('jassi','female',28,201),
-> ('tony','female',18,201),
-> ('kevin','female',18,202),
-> ('kello','male',28,203),
-> ('nicole','male',18,203),
-> ('jerry','male',48,204);
# 3.子查询
先获取jason的部门编号
select dep_id from emp1 where name = 'jason';
根据部门编号获取部门名称
select name from dep1 where id = 200;
整合
select name from dep1 where id = (select dep_id from emp1 where name = 'jason');
# 4.连表操作
select * from emp1,dep1; # 笛卡尔积
'''笛卡尔积效率求数据,效率太低,连表有专门的语法'''
4.1 inner join 内连接
拼接两边都有的字段数据
4.2 left join 左连接
以左表为基准,展示所有数据,没有对应数据用null填充
4.3 right join 右连接
以右表为基准,展示所有数据,没有对应数据用null填充
4.4 union 全连接
select * from emp1 left join dep1 on emp1.dep_id = dep1.id
union
select * from emp1 right join dep1 on emp1.dep_id = dep1.id;
Navicat可视化软件
一、介绍
可以充当很多数据库软件的客户端,主要用于MySQL
二、下载
1.网址
正版收费,可以百度破解版
三、主要功能介绍
1.连接
可以选择数据库软件,如MySQL、SQL server……等
2.新建查询
可以用SQL语句获取数据
3.库
3.1.逆向数据库到模型
直观看到库里表与表之间的关系
4.表
选中表 >>> 右键点击
4.1.打开表
可以修改数据值
4.2.设计表
可以修改字段
python操作MySQL
一、导入pymysql模块
pip install pymysql
二、代码演示
import pymysql
# 1.链接服务端
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='company',
charset='utf8mb4',
autocommit=True # 增删改查操作自动执行conn.commit二次确认
)
# 2.产生一个游标对象(等待输入命令)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 3.编写SQL语句
sql1 = 'select * from teacher'
# 4.发送给服务端
cursor.execute(sql1)
# 5.获取命令的执行结果
res2 = cursor.fetchone()
res3 = cursor.fetchall()
cursor.scroll(0, mode='absolute')
res4 = cursor.fetchmany(2)
print(res2)
print(res3)
print(res4)
# {'tid': 1, 'tname': '张磊老师'}
# [{'tid': 2, 'tname': '李平老师'}, {'tid': 3, 'tname': '刘海燕老师'}, {'tid': 4, 'tname': '朱云海老师'}, {'tid': 5, 'tname': '李杰老师'}]
# [{'tid': 1, 'tname': '张磊老师'}, {'tid': 2, 'tname': '李平老师'}]
三、获取结果
1.获取结果中的一条数据
cursor.fetchone()
2.获取结果中的所有数据
cursor.fetchall()
3. 获取结果中的指定数据
cursor.fetchmany()
4.基于数据集开头的位置往后移,类似于光标
cursor.scroll(0,mode='absolute')
5.基于数据集当前的位置往后移,类似于光标
cursor.scroll(0,mode='relative')
四、SQL注入问题
1.现象
只需要用户名就能登录
不需要用户名和密码也能登录
2.本质
利用一些特殊符号的组合产生了特殊的含义从而逃脱了正常的业务逻辑
3.解决方法
针对用户输入的数据不要自己处理,交给专门的方法自动过滤
sql = "select * from userinfo where name=%s and pwd=%s"
cursor.execute(sql,(username,pwd))
# 自动识别%s,并自动过滤各种符号,最后合并数据
补充
cursor.executemany()
五、小知识补充
1.as 语法
给字段起别名、起表名
2.comment 语法
给表、字段添加注释信息
create table server(is int) comment '阿巴阿巴'
create table t1(id int comment '用户编号',
name varchar(16) comment '用户名') comment '用户表';
'''
查看注释:
show create table
use information_schema
'''
3.concat、concat_ws 语法
concat用于分组之前多个字段数据的拼接
concat_ws如果有多个字段,并且分隔符一致,可以使用该方法减少代码
4.exists 语法
select * from userinfo where exists(select * from department where id<100)
exists 后面的SQL语句如果有结果,那么执行前面的SQL语句;如果没有就不执行
视图
一、介绍
SQL语句的执行结果是一张虚拟表,我们可以基于该表做其他操作
如果这张虚拟表需要频繁使用,为了方便,可以将虚拟表保存起来,宝尊之后就称之为“视图”(本质就是一张虚拟表)
事务
一、事务的四大特征(ACID)
A:原子性
事务是一个完整的操作,事务的各个步骤有一个不完成,就所有步骤全都不会完成
C:一致性
当事务完成时,数据必须处于一致状态
I:隔离性
对数据进行修改的所有并发事务是彼此隔离的。表明事务必须是独立的,他不应以任何方式依赖于或影响其他事物。
D:持久性
不管系统是否发生故障,事务处理的结果都是永久的
二、扩展重要知识
1.MySQL提供两种事务型存储引擎InnoDB和NDB cluster及第三方XtraDB、PBXT
2.事务处理中会反复出现的关键词
事务:transaction
回退:rollback
提交:commit
保留点:savepoint
作用:
为了支持回退部分事务处理,必须在事务处理块中合适的位置放置占位符,如果需要回退,可以回退到某个占位符(保留点)
# 保留点在执行rollback或者commit之后自动释放
创建占位符:savepoint
savepoint sp01;
回退到占位符地址:
rollback to sp01;
三、四种隔离级别
1.read uncommitted(未提交读)
事务中的SQL语句修改了数据,即使没有事务提交,其他事务也可以读取到未提交时修改后的数据。 —— 脏读现象
2.read committed(提交读=不可重复读)
大多数数据库系统的默认隔离级别
事务A在修改数据时,如果事务A没有提交事务,其他事务不会看到被修改后的数据,也就避免了脏读
但是有可能两个事物同时修改同一表格的数据,底层上会出现问题
3.repeatable read(可重复读)
在一个事务内,最开始读到的数据和事务结束前任意某时刻读到的数据出现不一致,出现幻读现象。
幻读:事务A读取数据,事务B修改添加了新的记录并提交,事务A再次读取数据,会出现幻行。
4.serializable(可串行读)
强制事务串行执行,很少使用该级别。
四、事务日志
1.优点
可以帮助提高事务的效率
存储引擎在修改标的大数据的时候,只需要修改其内存拷贝再把该修改记录到存储在硬盘上的事务日志中,而不用每次都将修改的数据本身存储到磁盘
MVCC多版本并发控制
一、特点
MVCC只能在 read committed(提交读)、repeatable read(可重复读)两种隔离级别下工作,其他两个不兼容(read uncommitted:总是读取最新 serializable:所有的行都加锁)
InnoDB的MVCC通过在每行记录后面保存两个隐藏的列来实现MVCC
一个列保存了行的创建时间
一个列保存了行的过期时间(或删除时间)本质是系统版本号
一个列保存了行的过期时间(或删除时间)本质是系统版本号
每开始一个新的事物版本号都会自动递增,事物开始时刻的系统版本号会作为事物的版本号用来和查询到的每行记录版本号进行比较
例如:刚插入第一条 数据的时候,我们默认事物id为1,实际是这样存储的
username | create_version | delete_version |
---|---|---|
jason | 1 |
可以看到我们在content
列插入了kobe这条数据,在create_version这列存储了1,1是这次插入操作的事物id
然后我们呢将jason修改为jason01,实际存储是这样的
username | create_version | delete_version |
---|---|---|
jason | 1 | 2 |
jason01 | 2 |
可以看到,update的时候,会先将之前的数据delete_version 标记为当前新的事物id,也就是2,然后将新数据写入,将新数据的create_version标记为新的事物id
当我们删除数据的时候,实际存储是这样的
username | create_version | delete_version |
---|---|---|
username | create_version | delete_version |
jasion01 | 2 | 3 |
由此当我们查询一条记录的时候,只有满足以下两个条件的记录才会被显示出来:
- 当事物id要大于或等于当前的create_version 值,这表示在事物开始签这行数据已经存在了。
- 当前事务id要小于delete_version 值,这表示在事务开始之后这行记录才被删除。
二、存储过程
1.类似于python中的自定义函数
语法格式
delmiter 临时结束符
create procedure 名字(参数,参数)
begin
sql语句;
end 临时结束符
delimiter ;
delimiter $$ #临时修改 结束符
create procedure p1(
in m int, in # in表示这个参数必须只能传入不能返回出去
in n int, in
out res int # out表示这个参数可以被返回出去,还有一个inot 表示即可传入也可以被返回出去
)
begin
select tanme from teacher where tid > m and tid < n;
set res=0; # 用来标志存储过程是否执行
end $$
delimiter ; #改回结束符
#针对 res 需要先提前定义
set @res=10; 定义
select @res; 查看
call p1(1.5,@res) 调用
select @res 查看
查看存储过程具体信息
show create procedure pro1;
查看你所有存储过程
show procedure status;
删除存储过程
drop procedure pro1;
三、内置函数
可以通过 help
函数名 查看帮助信息
移除指定字符
select Trim() # 默认移除两边空额
select LTrim
标签:总结,name,int,table,数据,id,select
From: https://www.cnblogs.com/Zhang614/p/16610421.html