mysql数据库基础知识点总结--看完即入门
疫情在家,在家简单复习了SQL数据库的基础知识。其实回过头来,当时本科时候学习的时候,还没有多大的感触。现在学习了这么多的语言和结构化知识,再回头来看这门语言,很多东西息息相关。就像是瞬间打通了六脉,很多东西之前没有理解的原理和方法,其实在过去的这段时间早已经深深的领悟了。
这篇基础的sql命令和基础介绍课程来自B站:
https://www.bilibili.com/video/av9252479?p=46
主讲人是燕十八老师,通篇没有废话,讲的非常流畅,推荐入门级的同学进行学习。
下面就总结一下课程算涉及到的语法知识:
desc 表名; – 查看表结构
1.导入sql语句
create table goods (
goods_id mediumint(8) unsigned primary key auto_increment,
goods_name varchar(120) not null default '',
cat_id smallint(5) unsigned not null default '0',
brand_id smallint(5) unsigned not null default '0',
goods_sn char(15) not null default '',
goods_number smallint(5) unsigned not null default '0',
shop_price decimal(10,2) unsigned not null default '0.00',
market_price decimal(10,2) unsigned not null default '0.00',
click_count int(10) unsigned not null default '0'
) engine=myisam default charset=utf8;
insert into `goods` values (1,'kd876',4,8,'ecs000000',1,1388.00,1665.60,9),
(4,'诺基亚n85原装充电器',8,1,'ecs000004',17,58.00,69.60,0),
(3,'诺基亚原装5800耳机',8,1,'ecs000002',24,68.00,81.60,3),
(5,'索爱原装m2卡读卡器',11,7,'ecs000005',8,20.00,24.00,3),
(6,'胜创kingmax内存卡',11,0,'ecs000006',15,42.00,50.40,0),
(7,'诺基亚n85原装立体声耳机hs-82',8,1,'ecs000007',20,100.00,120.00,0),
(8,'飞利浦[email protected]',3,4,'ecs000008',1,399.00,478.79,10),
(9,'诺基亚e66',3,1,'ecs000009',4,2298.00,2757.60,20),
(10,'索爱c702c',3,7,'ecs000010',7,1328.00,1593.60,11),
(11,'索爱c702c',3,7,'ecs000011',1,1300.00,0.00,0),
(12,'摩托罗拉a810',3,2,'ecs000012',8,983.00,1179.60,13),
(13,'诺基亚5320 xpressmusic',3,1,'ecs000013',8,1311.00,1573.20,13),
(14,'诺基亚5800xm',4,1,'ecs000014',1,2625.00,3150.00,6),
(15,'摩托罗拉a810',3,2,'ecs000015',3,788.00,945.60,8),
(16,'恒基伟业g101',2,11,'ecs000016',0,823.33,988.00,3),
(17,'夏新n7',3,5,'ecs000017',1,2300.00,2760.00,2),
(18,'夏新t5',4,5,'ecs000018',1,2878.00,3453.60,0),
(19,'三星sgh-f258',3,6,'ecs000019',12,858.00,1029.60,7),
(20,'三星bc01',3,6,'ecs000020',12,280.00,336.00,14),
(21,'金立 a30',3,10,'ecs000021',40,2000.00,2400.00,4),
(22,'多普达touch hd',3,3,'ecs000022',1,5999.00,7198.80,16),
(23,'诺基亚n96',5,1,'ecs000023',8,3700.00,4440.00,17),
(24,'p806',3,9,'ecs000024',100,2000.00,2400.00,35),
(25,'小灵通/固话50元充值卡',13,0,'ecs000025',2,48.00,57.59,0),
(26,'小灵通/固话20元充值卡',13,0,'ecs000026',2,19.00,22.80,0),
(27,'联通100元充值卡',15,0,'ecs000027',2,95.00,100.00,0),
(28,'联通50元充值卡',15,0,'ecs000028',0,45.00,50.00,0),
(29,'移动100元充值卡',14,0,'ecs000029',0,90.00,0.00,0),
(30,'移动20元充值卡',14,0,'ecs000030',9,18.00,21.00,1),
(31,'摩托罗拉e8 ',3,2,'ecs000031',1,1337.00,1604.39,5),
(32,'诺基亚n85',3,1,'ecs000032',4,3010.00,3612.00,9);
create table category (
cat_id smallint unsigned auto_increment primary key,
cat_name varchar(90) not null default '',
parent_id smallint unsigned
)engine myisam charset utf8;
INSERT INTO `category` VALUES
(1,'手机类型',0),
(2,'CDMA手机',1),
(3,'GSM手机',1),
(4,'3G手机',1),
(5,'双模手机',1),
(6,'手机配件',0),
(7,'充电器',6),
(8,'耳机',6),
(9,'电池',6),
(11,'读卡器和内存卡',6),
(12,'充值卡',0),
(13,'小灵通/固话充值卡',12),
(14,'移动手机充值卡',12),
(15,'联通手机充值卡',12);
CREATE TABLE `result` (
`name` varchar(20) DEFAULT NULL,
`subject` varchar(20) DEFAULT NULL,
`score` tinyint(4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
insert into result
values
('张三','数学',90),
('张三','语文',50),
('张三','地理',40),
('李四','语文',55),
('李四','政治',45),
('王五','政治',30);
create table a (
id char(1),
num int
)engine myisam charset utf8;
insert into a values ('a',5),('b',10),('c',15),('d',10);
create table b (
id char(1),
num int
)engine myisam charset utf8;
insert into b values ('b',5),('c',15),('d',20),('e',99);
create table m(
mid int,
hid int,
gid int,
mres varchar(10),
matime date
)engine myisam charset utf8;
create table t (
tid int,
tname varchar(20)
)engine myisam charset utf8;
insert into m
values
(1,1,2,'2:0','2006-05-21'),
(2,2,3,'1:2','2006-06-21'),
(3,3,1,'2:5','2006-06-25'),
(4,2,1,'3:2','2006-07-21');
insert into t
values
(1,'国安'),
(2,'申花'),
(3,'布尔联队');
create table mian ( num int) engine myisam;
insert into mian values
(3),
(12),
(15),
(25),
(23),
(29),
(34),
(37),
(32);
create table user (
uid int primary key auto_increment,
name varchar(20) not null default '',
age smallint unsigned not null default 0
) engine myisam charset utf8;
create table boy (
hid char(1),
bname varchar(20)
)engine myisam charset utf8;
insert into boy (bname,hid)
values
('屌丝','A'),
('杨过','B'),
('陈冠希','C');
create table girl (
hid char(1),
gname varchar(20)
)engine myisam charset utf8;
insert into girl(gname,hid)
values
('小龙女','B'),
('张柏芝','C'),
('死宅女','D');
1.insert:插入操作insert into t_user(userName,password) values('anti','222222')
; 添加数据 列与值严格对应 数字不必加单引号,字符串必须加单引号
2.update:更新操作update t_user set password=333333 WHERE userName='anti';
– update:更新数据 如果where不添加指定行或者条件,则会影响所有行操作update t_user set userName='weiling',password=124578 where id=3;
注意连接之间用逗号
3.delete 删除操作
要删除只可能删除一行,不可能删除一行中的某个数据
delete from t_user where id=1;
delete * from t_user 全部删除表,后果很严重
4.查数据
select * from t_user where id=2;
select userName from t_user where password=333333; 查询密码符合条件的userName,只显示userName
5.在指定位置增加新的一列属性
alter table t_user add column price varchar(10) after password
update t_user set price=100 where id=1;
update t_user set price=200 where id=2;
update t_user set price=300 where id=3;
alter table t_user add column count varchar(10) after price;
update t_user set count= 1 where id=1;
update t_user set count=2 where id=2;
update t_user set count=3 where id=3;
alter table t_user add column phone varchar(10) after count;
update t_user set phone= '苹果1' where id=1;
update t_user set phone='苹果2' where id=2;
update t_user set phone='小米' where id=3;
alter table t_user add column cat_id int after phone;
update t_user set cat_id= 5 where id=1;
update t_user set cat_id=6 where id=2;
update t_user set cat_id=5 where id=3;
6.select查询模型
列是变量,变量可以计算
where是表达式,值为真假
select userName from t_user where password=222222;
select * from t_user where 1; where后面接的是表达式,1为真,所以会显示所有的数据
select id,userName,password+1 from t_user where 1; 列是变量,可以计算。在原来的password基础上+1
select userName from t_user where password=222222 or password=333333;
select userName from t_user where password in(222222,333333); 如果不用or也可以用in进行操作
select * from t_user where price >= 99 and price<=201;
select * from t_user where price between 99 and 201; 两种写法
select * from t_user where id!=1 and id!=3; 不属于1和3的序列
select * from t_user where id not in(1,3);
select * from t_user where id=3 and (price<100 or price>200) and count>2; 取出第3个序列下面价格小于100或者价格大于200,并且点击量大于2的商品(条件较多时,建议加括号区分优先级)
like:模糊查询
%:通配任意字符
_:通配单一字符
select * from t_user where phone like '苹果%'
select id,userName,password,price,count,concat('htc',substring(phone,3)) from t_user where phone like '苹果%' 将带苹果的标识改为htc
7.group分组与统计函数
max()
count():是属行的个数
min()
avg()
sum():统计数字相加的总数
select avg(price) from t_user; 求平均价格
select cat_id,avg(price) from t_user group by cat_id; group按照cat_id进行分组
select cat_id,max(price) from t_user group by cat_id; 查询 cat_id下最贵的价格
8.having
select userName,price,count,(price-count) as sheng from t_user where sheng>100; where是针对磁盘上的数据文件发挥作用,但是磁盘上没有sheng这个属性,只有price和count属性,所以会报错
select userName,price,count,(price-count) as sheng from t_user having sheng>100; 这时候需要用到having,之前的sheng结果已经放入到内存中了,having可以读取内存中的结果
创建新表
-- create table grade
-- (
-- name varchar(255),
-- subject varchar(255),
-- score int
-- )
insert into grade2 values(1,'张三','数学',90,3);
insert into grade2 values(2,'张三','语文',50,5);
insert into grade2 values(3,'张三','地理',40,7);
insert into grade2 values(4,'李四','语文',55,1);
insert into grade2 values(5,'李四','数学',45,6);
insert into grade2 values(6,'王五','政治',30,2);
insert into grade2 values(7,'赵六','政治',90,4);
insert into grade2 values(8,'赵六','语文',80,8);
– 查询两门及两门以上不及格同学的平均成绩
– 思路:先统计每位同学不及格总共的门数,然后利用having统计符合条件的同学的平均成绩
select name,(sum(score<60)) as pj,avg(score) from grade group by name having pj>=2;
9.order by:进行排序
asc:升序 desc:降序
select name,subject,score from grade order by score; -- 利用成绩进行排序(默认升序)
select name,subject,score from grade order by score desc; -- 降序排列
select name,subject,score,num from grade2 order by score; -排序之后还可以再次进行排序 多列排序
10.limit:限制取出条目:类似于pytohn中的head 取出多少个数据
有两个参数:前面参数代表 按照排序从第几个数据开始,后一个参数代表取出的数据个数
select * from grade2 order by score limit 2,3; -- 升序,从排名第二开始,取出三个数据
11.子句的查询陷阱
5种子句是有严格的顺序,where,group by,having,order by,limit
引出子查询
12.where型子查询
–查询成绩最高的分数
select * from grade2 order by score desc limit 0,1; -- 一般不推荐用排序,因为如果数据多,内存消耗量大
select * from grade2 where score=100; -- 这是已知最大成绩可以这样查询
select max(score) from grade2
select * from grade2 where score=(select max(score) from grade2);-- where子查询
13.from 型子查询
select name,score from(select * from grade2 order by score) as tmp order by score desc; -- 注意,第一个子查询一定要起一个别名 as..
14.exists子查询
15.新手1+N查询模式
-- 查询价格大于2000元的商品及其栏目名称(cat_name)
select cat_name from category,goods where category.cat_id=goods.cat_id and goods.shop_price>=3000;
15.内连接查询 inner join on 查询的是两个表都有的共同数据
select * from boy;
select * from girl;
select boy.hid,boy.bname,girl.hid,girl.gname from boy inner join girl on boy.hid=girl.hid;
16.左连接及右连接查询
左连接以左边数据为主,查询右边相关数据,查不到的补Null
select boy.hid,boy.bname,girl.hid,girl.gname from boy left join girl on boy.hid=girl.hid;
右连接以右边数据为主,查询左边相关数据,查不到的补Null
select boy.hid,boy.bname,girl.hid,girl.gname from boy right join girl on boy.hid=girl.hid;
-- 取出所有商品的商品名,栏目名价格
select goods_id,cat_name,goods_name,shop_price from goods left join category on goods.cat_id=category.cat_id;
-- 取出第4个栏目下的商品的商品名,栏目名与品牌名
select goods_id,cat_name,goods_name,shop_price from goods left join category on goods.cat_id=category.cat_id where goods.cat_id=4;
17.union
把2条或者多条sql的查询结果合并成一个结果集 可以从一张表,也可以从多张表进行合并
需要注意:使用union需要满足各语句取出的列数相同,但是列名不一定要相同,列名称会使用第一条sql的列名称为准
select * from a union select * from b; -- 如果碰到完全相同的行,将会被合并 本来是8条数据,因为两个表中各存在一个一模一样的数据,故被舍去.
select * from a union all select * from b; -- 合并是非常耗时的,它会一个字段一个字段进行比较,判断是否存在相同的数据,进而舍去.而使用 union all 就不需要比较字段,会直接进行合并,这样就得到8行数据了
select goods_id,cat_id,goods_name,shop_price from goods where cat_id=4 union select goods_id,cat_id,goods_name,shop_price from goods where cat_id=2; -- 一个并集
union查询的内部子句中不用写order by子句,意义不大!因为各自对部分进行排序没有什么意思,但是可以对查询合并后总的结果集进行排列
-- 将A、B表中id值相同的两个num值相加
select id, sum(num) from(select * from a union all select * from b) as temp group by id;
2.SQL语言之DDL部分@数据定义语言【建库、建表】–“总经理”
1.创建表table
建"表"过程就是申明数据库中各个"列"的过程
creat table_name (
列名 列类型 [列属性 列默认值]
)
ENGINE = 存储引擎 default charset=字符集;
列的类型知识:
数值型:整型、浮点型、定点型
整型列:
int 4个字节【1个字节=8位 4个字节=32位-- 也就是"1"这个int型只占了32位中1个位】,非常浪费空间
mediumint 3个字节
smallint 2个字节
tinyint 1个字节 【8位==> 0-255 或 -128 - 127】
bigint 8个字节
1)像tinyint中,默认数值型都是对半正负分配的==>即:正常情况下tinyint是不能存储大于128的数字的! 存储的是-128~127之间的数字
那么,如何让tinyint存储0-255之间的数呢?
使用unsigned属性【无符号】修饰;
create table test2(
num1 tinyint
)
insert into test2 values(255); 新创建一个表,直接插入255是不能成功的,因为默认范围是-128~127
alter table test2 add column num2 tinyint unsigned after num1;
insert into test2 values(120,255); 我们新申请了一个列num2,并且用unsigned定义,这时候就可以插入255,范围是0~255
alter table test2 add column num3 tinyint(4) zerofill after num2; -- 填充固定宽度为4
insert into test2 values(12,28,7);
insert into test2 values(13,29,71);
zerofill==>用0填充至固定宽度【学号:1->0001;255 ->0255】
M -> 宽度 tinyint(5)–>宽度为5;varchar(10)->宽度为10
desc test2; 通过调用,我们发现zerofill属性就已经代表了该类型为是unsigned属性了==>负数不需要用0填充
M属性只有和zerofill配合使用才有意义!宽度是指0填充的宽度,而不是指该列存储的宽度【如:tinyint(1) 可以存储111】
2.浮点列[float/doule]与定点列[decimal] 存放小数
浮点列:float/double (M,D) [UNSIGNED] [ZEROFILL] – M表示精度【总位数(不含小数点)】,D表示小数点后面的位数
float(3,2)==>存9.99正确 总位数为3,小数点后面2位
double:和float一样,唯一区别是范围比float大。
定点列decimal[整数部分和小数部分分开来存储的]
浮点数是有精度损失的!定点列更准确
create table t4(
salary1 double(9,2),
salary2 decimal(9,2)
)
insert into t4 values(1234567.25,1234567.25); double浮点型显示1234567.23,定点列显示1234567.25 所以浮点型是有损失的
select * from t4;
3字符型列[char/varchar/text]
char(M)–定长;varchar(M) – 变长
例如:
char(10) – 放10个字符长度,但是存放1个字符,在内存中依然是占10个字符长度
–char(M) 在磁盘上就占M个字节,磁盘空间利用率可能达到100%
varchar(10) – 放10个字符长度,但是存放1个字符,在内存中就占了1个字符长度的空格键
–varchar(M) 在内存表中存储时,在表头会增加1-2说明字节存储该字符串长度==>那么内存寻址的时候就能准确找到每一行数据==>实际varchar占M+[1/2]字节
一般对于M较小的,都用char! 定长速度比较快
1).因为varchar的利用率是不可能达到100%!
2).内存的定长寻址会快很多
3).char型,如果不够M个宽度,内存存储时候会用空格在字符右边补齐,取出时候把右侧空格删除
如果用char存储’ hello ‘,取出之后’ hello’;用varchar存,取出时候’ hello ’
char(M),varchar(M)限制的是字符,不是字节
②text – 大文本类型;blob – 二进制类型
例如:论文、博客…等大段文本text
图像、音频等二进制信息用blob类型来存储
意义:blob是使用二进制来存储信息的,因此不需要考虑字符集的问题!
例如0xFF这个字节,在ASCII字符集中被认为是非法的,在入库的时候就会被过滤掉!如果使用blob来存储则不会被过滤
③enum(‘value1’,‘value2’,…) – 枚举类型;是定义好值就在某几个枚举范围内
set(‘value1’,‘value2’,…) – 集合类型
例如:
create table t7(
gender enum(‘男’,‘女’) 以后gender范围只可能填写男或者女
gender2 enum(‘男’,‘女’) 以后gender2范围可能填写男或者女或者男女 ,可以是集合
)
enum(‘男’,‘女’) ☛ 该列所存储的值就只能是’男’或’女’ ☛ 是个单选值存储
set(‘value1’,‘value2’,…) ☛ 是个复选值存储,但值也只能在列举的元素中选取
注意:set()最多只能列举64个值!
4. 日期时间型列[year/Date/time/datetime]
year 年 [1个字节] 范围:[1901-2155] ☛ 在insert是,可以简写年后面对两位,但是这样不推荐
【00-69】+2000;【70-99】+1900 ☛ 填写两位,表示1970-2069年✘不要只写后面2个数字
Date 日期 1994-10-29
☛ 以’YYYY-MM-DD HH:MM:SS’格式检索和显示DATETIME值。支持的范围为’1000-01-01 00:00:00’到’9999-12-31 23:59:59’
time 时间 13:02:29
☛ 用’YYYY-MM-DD’格式检索和显示DATE值。支持的范围是’1000-01-01’到 ‘9999-12-31’
datetime 日期
☛ 以’YYYY-MM-DD HH:MM:SS’格式检索和显示DATETIME值。支持的范围为’1000-01-01 00:00:00’到’9999-12-31 23:59:59’
int unsigned 时间戳 1970-01-01 00:00:00 到当前的秒数
☛ 一般存注册时间,商品发布时间等,并不是用datetime,而是用时间戳存储,因为datetime存储虽然直观,但不便计算
5 列属性 默认值[ default ]&& not null
1.NULL不便于查询【注意:空字数串,0都不是NULL–NULL是什么都没有,是不存在】
2.Null的索引效果不高
3.实用中,避免列的值为NULL
案例:
id int not null default 0; – 默认值是0,不为空
6 列属性 ☛ 主键[ primary key ] && 自增[ auto_increment ]
1.主键 primary key:此列不重复,能够区分每一行==>列名 primary key auto_increment
案例:
create table t1(
id int primary key
)
或者
create table t2(
id int,
primary key(id)
)
一般主键和自增是一起使用的[int类型],不一定一要一起使用!一张表中只能有一个自增的列!
一张表只能1列为auto_increment,且此列必须加索引.
小技巧:
1.很多时候都是用tinyint存储☛性别:0/1 --> 男/女;体重:tinyint 【0-255】…
2.定长存储寻址快,效率高–常用的字段建议定长存储【对于一张表,只有一个变长大字段其他都是定长字段情况下,可考虑将变长单独分出来】
3.一般mysql的列名都用小写
– 修改表的名字
rename table x1 to x2;
7 列的增add/删/改 ☛ 这是对表结构的修改
增:alter table 表名 add 列名 列类型 [列属性] – 默认该列是存放在表最后的【使用 after 列名 --放在指定列】
删:alter table 表名 drop column 列名 列类型 [列属性] alter table t1 drop name;
改:alter table 表名 change 旧列名 新列名 [新列类型] [新列属性] 可以修改列名和属性
改:alter table 表名 modify 列名 [新列类型] [新列属性] --modify 不能修改列名,只能修改列的属性
3. 视图
需要知道视图的概念,并且会建立视图
1).什么是视图?
view 又称虚拟表,view其实就一条查询SQL语句的结果集==>将常用的SQL查询结果集虚拟为一张表存放在内存中
create view as 视图名 (查询SQL语句结果集);–当再次使用时:select * from 视图名
create view vgood as select goods_id,goods_name,market_price,shop_price,(market_price+shop_price) as sheng from goods; 根据需要的数据,创建新的视图
select * from vgood;
2).视图有什么用?【视图实际上存储的就是SQL语句】
1.权限的控制!比如:某几个列允许用户查询,而其他列不允许,可以通过视图开放其中的一部分列,达到权限的控制
create view vgood2 as select goods_id,goods_name,shop_price,(market_price+shop_price) as sheng from goods; 只开放本地价格,开放一部分权限
2.简化复杂的查询!比如:查询每个栏目下的商品的平均价格并按平均价格排序,然后查出平均价格前3高的栏目
①create view v as select cat_id, avg(shop_price) as pj from goods group by cat_id
②select * from v order by pj limit 0,3
3).视图能不能更新删除修改?
1.视图【虚拟表】 是物理表的一个"投影",两者是相互影响的 如果视图的每一行与物理表是一一对应的.那么,更改物理表,虚拟表也会更改,同理,更改虚拟表,物理表也会更改!
但是:如果视图中表的行是由物理表多行经过计算得到的结果,view是不可以更新的.
①create view as v select cat_id, avg(shop_price) as pj from goods group by cat_id
②update v set pj = 80 where cat_id=11;–报错!因为修改结果不能正确映射回到goods表中所有shop_price中
同理:增加和删除操作也是和修改一样
4).视图放在什么地方?
1.对于简单查询形成的view;再对view进行查询时,如where,order等等,可以把建视图的语句和查询视图的语句合并成查物理表的语句,这种视图的算法叫做合并(merge)
create view vgood3 as select goods_id,goods_name,market_price from goods;
select * from vgoods order by market_price limit 0,3;
select goods_id,goods_name,market_price from goods order by market_price limit 0,3;
2.也有可能视图的语句本身比较复杂,很难再和查询视图的语句合并.mysql可以先执行视图的创建语句,把结果集形成内存中的临时表,然后再去查临时表.
MySQL数据库中可以通过algorithm(算法)定义对视图的处理情况 create algorithm = merge/temptalbe view v_name as …
[不写该属性,则由MySQL自行判断]
— 表/视图的管理语句
查看所有表:show tables;
查看表结构:desc 表名/视图名
查看建表过程:show create table 表名
查看键视图过程: show create view 视图名
查看表信息:show table status / show table status where name=‘goods’;
删除表:drop table 表名
删除视图:drop view 视图名
改表名:rename table oldname to newname
清空表数据:truncate 相当于删除表,再重建
4. 存储引擎[ENGINE]
1).什么是存储引擎?
即:保存"数据"的形式【格式】
MYISAM:【处理快-相对不安全-不支持事务】
good.frm–说明书[声明表结构的表具体语句]
good.MYD–数据内容
goods.MYI–目录[索引文件]
InnoDB【安全-处理慢-支持事务】–只有.frm文件,其余表的其余全部内容存放在了一个文件中
Memory【存放在内存中–一关机就没有了】
5.字符集与乱码问题
1.什么是乱码?
对计算机来说,没有"乱码",只有0/1==> 乱码只是人看不懂而已,计算机都看得懂.
2.为什么会乱码?
1.导致原因:文字本来的字符集与展示的字符集不一致
一般统一utf8;
2.服务器和客户端字符集不一致!
客户端[GBK提交数据] 连接器处理[转换为数据库字符集] 数据库[UTF8存放数据]【无论连接器转不转,最终存放到数据库中都是UTF8】
数据库[UTF8存放数据] 连接器处理[转换为客户端字符集] 客户端[GBK显示数据]
☛由于客户端和数据库字符集不同导致的乱码 在提交和显示数据的时候,要"说清楚"字符集
"我"要什么字符集? 客户端:set character_set_client =gbk;【谁连接服务器谁就是客户端,客户端字符集是多变的】
"你"接受什么字符集? 数据库:set character_set_results=utf8;
"转换"用什么字符集?=连接器:set character_set_connection = gbk/utf8[都可以]
只需要将3者的字符集设置一致不会乱码了! set names gbk/utf8 1句好比3句强
UTF8:包含中文,韩文,日文,英语,繁体字…国际化
GBK:只有简体中文
gbk2123:简体中文+英文
3.怎么能不乱码?
①文件保存时是否保存为utf8格式
②HTML页面显示时候 :
③创建数据表的时候: create table () charset utf8;
④查询数据的时候:set names utf8;
4.什么是字符校对集?
[utf8-bin==>bin : 二进制排序]==>校对集就是查询排序的标准
6. 索引[ index ]
索引是数据的目录,能快速定位行数据的位置. 它类似于数据结构的二叉树,左子树小于中间节点,右子树大于中间节点,通过这样的索引,查询数据速度就是一个有一个的二分查找,节约了不少时间.
索引提高了查询速度,但是降低了增删改的速度,并非加的越多越好.
一般在查询频率高的列上加,而且在重复度低的列上加更好.
索引类型
key 列名(索引名) 普通索引 纯粹提高查询速度
unique key 列名(索引名) 唯一索引 提高速度,且约束数据唯一性
primary key 列名 主键索引 唯一主键
fulltext 全文索引 ==> 在中文环境下,基本不起作用,要分词索引,一般用第三方解决方案(如:sphinx)
索引长度:
[在建立索引时,对列中一部分字符进行索引]
unique key / key 列名(索引名 (索引长度) )
例如:对于唯一的Email,形式都是…@qq.com email char(20) unique key(10) – 只对前10个字符建立索引
多列索引:
[在建立索引时,对2个或多个列进行索引]
冗余索引:在某个列上可能存在多个索引
[索引存在覆盖]==>冗余索引有时候在开发中是必要的
操作索引:
1.查看索引:show index from 表名;
2.添加索引:alter table table_name add index column( index_name )
3.删除索引:alter table 表名 drop index 索引名 / drop index 索引名 from 表名
4.添加主键索引: alter table 表名 add primary key 列名; – 主键只有一个索引,不需要索引名 alter table 表名 add unique key 索引名(列名);
删除主键索引: alter table 表名 drop primary key;
1.explain select … 查看该语句执行信息 可以查看使用到的索引
2.索引有一个左前缀查找原则==> "…xxx"这样对xxx发挥不了作用
1).查询方式?
当表中有大量记录时,若要对表进行查询:
①全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录
☛消耗大量数据库系统时间,并造成大量磁盘I/O操作
②第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录
2).什么是索引?
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息!
–相当于图书的"目录",根据目录,迅速定位查找内容的位置
3).索引优/缺点?
优点:
①加快了查询时对数据的检索速度
②创建唯一性索引,保证数据库表中每一行数据的唯一性
③加速表和表之间的连接
④在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间
缺点:
①索引是另外独立于数据外存放的一个二进制文件==>需要占物理空间( .MYI )
②对表数据进行增、删和改的维护操作时,索引也要动态的变化==>降低了数据增、删、改的维护速度
☛在创建索引之前,您必须确定要使用哪些列以及要创建的索引类型!
☛索引不是越多越好==>一般在查询频率多、且重复度小的列上加!
例如:性别和身份号都需要频繁查询,且表数据量大
==>性别:就只有男和女,定位的时候有太多重复的了,添加索引反而是占用了空间!
==>身份证号:添加索引,身份证号是唯一的,只要快速找到索引就能快速定位
7. 常用九大类函数==>看一次就好!要用的时候至少知道
数据库是用来存储管理数据的,能够少用函数来处理尽量少用==>效率慢
1)、数学函数
abs(x) 返回x的绝对值
bin(x) 返回x的二进制(oct返回八进制,hex返回十六进制)
ceiling(x) 返回大于x的最小整数值==>向上取整
exp(x) 返回值e(自然对数的底)的x次方
floor(x) 返回小于x的最大整数值==>向下取整
greatest(x1,x2,...,xn)返回集合中最大的值
least(x1,x2,...,xn) 返回集合中最小的值
ln(x) 返回x的自然对数
log(x,y)返回x的以y为底的对数
mod(x,y) 返回x/y的模(余数)
pi()返回pi的值(圆周率)
rand()返回0或1的随机值,可以通过提供一个参数(种子)使rand()生成器生成1.
round(x,y)返回参数x的四舍五入的有y位小数的值
sign(x) 返回代表数字x的符号的值
sqrt(x) 返回一个数的平方根
truncate(x,y) 返回数字x截短为y位小数的结果
2)、聚合函数(常用于group by从句的select查询中)
avg(col)返回指定列的平均值
count(col)返回指定列中非null值的个数
min(col)返回指定列的最小值
max(col)返回指定列的最大值
sum(col)返回指定列的所有值之和
group_concat(col) 返回由属于一组的列值连接组合而成的结果
3)、字符串函数
ascii(char)返回字符的ascii码值
bit_length(str)返回字符串的比特长度
concat(s1,s2...,sn)将s1,s2...,sn连接成字符串
concat_ws(sep,s1,s2...,sn)将s1,s2...,sn连接成字符串,并用sep字符间隔
insert(str,x,y,instr) 将字符串str从第x位置开始,y个字符长的子串替换为字符串instr,返回结果
find_in_set(str,list)分析逗号分隔的list列表,如果发现str,返回str在list中的位置
lcase(str)或lower(str) 返回将字符串str中所有字符改变为小写后的结果
left(str,x)返回字符串str中最左边的x个字符
length(s)返回字符串str中的字符数
ltrim(str) 从字符串str中切掉开头的空格
position(substr,str) 返回子串substr在字符串str中第一次出现的位置
quote(str) 用反斜杠转义str中的单引号
repeat(str,srchstr,rplcstr)返回字符串str重复x次的结果
reverse(str) 返回颠倒字符串str的结果
right(str,x) 返回字符串str中最右边的x个字符
rtrim(str) 返回字符串str尾部的空格
strcmp(s1,s2)比较字符串s1和s2
trim(str)去除字符串首部和尾部的所有空格
ucase(str)或upper(str) 返回将字符串str中所有字符转变为大写后的结果
4)、日期和时间函数
curdate()或current_date() 返回当前的日期
curtime()或current_time() 返回当前的时间
date_add(date,interval int keyword)返回日期date加上间隔时间int的结果(int必须按照关键字进行格式化),如:selectdate_add(current_date,interval 6 month);
date_format(date,fmt) 依照指定的fmt格式格式化日期date值
date_sub(date,interval int keyword)返回日期date加上间隔时间int的结果(int必须按照关键字进行格式化),如:selectdate_sub(current_date,interval 6 month);
dayofweek(date) 返回date所代表的一星期中的第几天(1~7)
dayofmonth(date) 返回date是一个月的第几天(1~31)
dayofyear(date) 返回date是一年的第几天(1~366)
dayname(date) 返回date的星期名,如:select dayname(current_date);
from_unixtime(ts,fmt) 根据指定的fmt格式,格式化unix时间戳ts
hour(time) 返回time的小时值(0~23)
minute(time) 返回time的分钟值(0~59)
month(date) 返回date的月份值(1~12)
monthname(date) 返回date的月份名,如:select monthname(current_date);
now() 返回当前的日期和时间
quarter(date) 返回date在一年中的季度(1~4),如select quarter(current_date);
week(date) 返回日期date为一年中第几周(0~53)
year(date) 返回日期date的年份(1000~9999)
一些示例:
获取当前系统时间:
select from_unixtime(unix_timestamp());
select extract(year_month from current_date);
select extract(day_second from current_date);
select extract(hour_minute from current_date);
返回两个日期值之间的差值(月数):select period_diff(200302,199802);
在mysql中计算年龄:
select date_format(from_days(to_days(now())-to_days(birthday)),'%y')+0 as age from employee;
这样,如果brithday是未来的年月日的话,计算结果为0。
下面的sql语句计算员工的绝对年龄,即当birthday是未来的日期时,将得到负值。
select date_format(now(), '%y') - date_format(birthday, '%y') -(date_format(now(), '00-%m-%d') < date_format(birthday, '00-%m-%d')) as age from employee
5)、加密函数
aes_encrypt(str,key) 返回用**key对字符串str利用高级加密标准算法加密后的结果,调用aes_encrypt的结果是一个二进制字符串,以blob类型存储
aes_decrypt(str,key) 返回用**key对字符串str利用高级加密标准算法解密后的结果
decode(str,key) 使用key作为**解密加密字符串str
encrypt(str,salt) 使用unixcrypt()函数,用关键词salt(一个可以惟一确定口令的字符串,就像钥匙一样)加密字符串str
encode(str,key) 使用key作为**加密字符串str,调用encode()的结果是一个二进制字符串,它以blob类型存储
md5() 计算字符串str的md5校验和
password(str) 返回字符串str的加密版本,这个加密过程是不可逆转的,和unix密码加密过程使用不同的算法。
sha() 计算字符串str的安全散列算法(sha)校验和
示例:
select encrypt('root','salt');
select encode('xufeng','key');
select decode(encode('xufeng','key'),'key');#加解密放在一起
select aes_encrypt('root','key');
select aes_decrypt(aes_encrypt('root','key'),'key');
select md5('123456');
select sha('123456');
6)、控制流函数
mysql有4个函数是用来进行条件操作的,这些函数可以实现sql的条件逻辑,允许开发者将一些应用程序业务逻辑转换到数据库后台。
mysql控制流函数:
case when[test1] then [result1]...else [default] end如果testn是真,则返回resultn,否则返回default
case [test] when[val1] then [result]...else [default]end 如果test和valn相等,则返回resultn,否则返回default
if(test,t,f) 如果test是真,返回t;否则返回f
ifnull(arg1,arg2) 如果arg1不是空,返回arg1,否则返回arg2
nullif(arg1,arg2) 如果arg1=arg2返回null;否则返回arg1
这些函数的第一个是ifnull(),它有两个参数,并且对第一个参数进行判断。
==>如果第一个参数不是null,函数就会向调用者返回第一个参数;如果是null,将返回第二个参数。
如:select ifnull(1,2), ifnull(null,10),ifnull(4*null,‘false’);
nullif()函数将会检验提供的两个参数是否相等,如果相等,则返回null,如果不相等,就返回第一个参数。
如:select nullif(1,1),nullif(‘a’,‘b’),nullif(2+3,4+1);
和许多脚本语言提供的if()函数一样,mysql的if()函数也可以建立一个简单的条件测试,这个函数有三个参数:
==>第一个是要被判断的表达式,如果表达式为真,if()将会返回第二个参数,如果为假,if()将会返回第三个参数。
如:selectif(1<10,2,3),if(56>100,‘true’,‘false’);
if()函数在只有两种可能结果时才适合使用。然而,在现实世界中,我们可能发现在条件测试中会需要多个分支。
—在这种情况下,mysql提供了case函数,它和php及perl语言的switch-case条件例程一样。
case函数的格式有些复杂,通常如下所示:
case [expression to be evaluated]
when [val 1] then [result 1]
when [val 2] then [result 2]
when [val 3] then [result 3]
…
when [val n] then [result n]
else [default result]
end
这里,第一个参数是要被判断的值或表达式,接下来的是一系列的when-then块,每一块的第一个参数指定要比较的值,如果为真,就返回结果。
所有的when-then块将以else块结束,当end结束了所有外部的case块时
==>如果前面的每一个块都不匹配就会返回else块指定的默认结果。如果没有指定else块,而且所有的when-then比较都不是真,mysql将会返回null。
case函数还有另外一种句法,有时使用起来非常方便,如下:
case
when [conditional test 1] then [result 1]
when [conditional test 2] then [result 2]
else [default result]
end
这种条件下,返回的结果取决于相应的条件测试是否为真。
示例:
mysql>select case 'green'
when 'red' then 'stop'
when 'green' then 'go' end;
select case 9 when 1 then 'a' when 2 then 'b' else 'n/a' end;
select case when (2+2)=4 then 'ok' when(2+2)<>4 then 'not ok' end asstatus;
select name,if((isactive = 1),'已**','未**') as result fromuserlogininfo;
select fname,lname,(math+sci+lit) as total,
case when (math+sci+lit) < 50 then 'd'
when (math+sci+lit) between 50 and 150 then 'c'
when (math+sci+lit) between 151 and 250 then 'b'
else 'a' end
as grade from marks;
select if(encrypt('sue','ts')=upass,'allow','deny') as loginresultfrom users where uname = 'sue';#一个登陆验证
7)、格式化函数
date_format(date,fmt) 依照字符串fmt格式化日期date值
format(x,y) 把x格式化为以逗号隔开的数字序列,y是结果的小数位数
inet_aton(ip) 返回ip地址的数字表示
inet_ntoa(num) 返回数字所代表的ip地址
time_format(time,fmt) 依照字符串fmt格式化时间time值
其中最简单的是format()函数,它可以把大的数值格式化为以逗号间隔的易读的序列。
示例:
select format(34234.34323432,3);
select date_format(now(),'%w,%d %m %y %r');
select date_format(now(),'%y-%m-%d');
select date_format(19990330,'%y-%m-%d');
select date_format(now(),'%h:%i %p');
select inet_aton('10.122.89.47');
select inet_ntoa(175790383);
8)、类型转化函数
为了进行数据类型转化,mysql提供了cast()函数,它可以把一个值转化为指定的数据类型。类型有:binary,char,date,time,datetime,signed,unsigned 示例:
select cast(now() as signed integer),curdate()+0;
select 'f'=binary 'f','f'=cast('f' as binary);
9)、系统信息函数
database() 返回当前数据库名
benchmark(count,expr) 将表达式expr重复运行count次
connection_id() 返回当前客户的连接id
found_rows() 返回最后一个select查询进行检索的总行数
user()或system_user() 返回当前登陆用户名
version() 返回mysql服务器的版本
示例:
select database(),version(),user();
selectbenchmark(9999999,log(rand()*pi()));#该例中,mysql计算log(rand()*pi())表达式9999999次。
create table account(
id int,
name char(10),
money int
)engine innodb charset utf8;
insert into account values(1,'zhangsan',5000);
insert into account values(2,'lisi',5000);
update account set money=money+100 where id=2;
8. 事务的概念
1.什么是事务?
将一个业务下的SQL语句作为一个单元统一操作==>“同生共死”!【MyISAM不支持事务】
例如:A"打账"500给B,打完之后A减少500,B增加500!如果这两个动作有一个没完成则整个打账过程取消失败–[原子性]
2.如何启用事务?
start transaction;
3.如何结束事务?
commit;
4.如何撤销事务?【回滚事务】
rollback;
事务的中间状态是不可见的–隔离性
事务发生结束了之后是不能恢复的–持久性
事务之前和之后它们的业务逻辑上要保持一致!两人总账额度9000,相互转帐后依然是9000 – 一致性
总结
对于初学者来说掌握视频中所提及的基础语法已经满足日常开发中的基本需要。如果在上述基础已经完全掌握的情况下,可以再继续进行触发器等高阶知识点的学习,最好循序渐进,不要囫囵吞枣。