简单复习了SQL数据库的基础知识。其实回过头来,当时本科时候学习的时候,还没有多大的感触。现在学习了这么多的语言和结构化知识,再回头来看这门语言,很多东西息息相关。就像是瞬间打通了六脉,很多东西之前没有理解的原理和方法,其实在过去的这段时间早已经深深的领悟了。
这篇基础的sql命令和基础介绍课程来自B站:
主讲人是燕十八老师,通篇没有废话,讲的非常流畅,推荐入门级的同学进行学习。
下面就总结一下课程算涉及到的语法知识:
认识SQL
- SQL(structured Query Language) 结构化查询语言
- What型的语言而言How型的语言,只需要写入你需要查找的内容,不关心内部如何实现
- DML:数据操作语言,SQL中处理数据等操作系统的数据操纵语言(使用者的角度,80%)
- DDL:数据定义语言,用于定义和管理SQL数据库中的所有对象的语言(建设者的角度,建表、建库、键视图等等,15%)
- DCL:数据控制语言,用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等(管理员角度,DBA,5%)
insert操作
先导入提供的sql语句
createtable goods (goods_id mediumint(8)unsignedprimarykeyauto_increment,goods_name varchar(120)notnulldefault'',cat_id smallint(5)unsignednotnulldefault'0',brand_id smallint(5)unsignednotnulldefault'0',goods_sn char(15)notnulldefault'',goods_number smallint(5)unsignednotnulldefault'0',shop_price decimal(10,2)unsignednotnulldefault'',market_price decimal(10,2)unsignednotnulldefault'',click_count int(10)unsignednotnulldefault'0')engine=myisam defaultcharset=utf8;insertinto`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,2,24.00,3),(6,'胜创kingmax内存卡',11,0,'ecs000006',15,42.00,50.40,0),(7,'诺基亚n85原装立体声耳机hs-82',8,1,'ecs000007',20,10,12,0),(8,'飞利浦9@9v',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,130,,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,315,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,230,276,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,28,336.00,14),(21,'金立 a30',3,10,'ecs000021',40,200,240,4),(22,'多普达touch hd',3,3,'ecs000022',1,5999.00,7198.80,16),(23,'诺基亚n96',5,1,'ecs000023',8,370,444,17),(24,'p806',3,9,'ecs000024',100,200,240,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,10,0),(28,'联通50元充值卡',15,0,'ecs000028',0,45.00,5,0),(29,'移动100元充值卡',14,0,'ecs000029',0,9,,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,301,3612.00,9);createtable category (
cat_id smallintunsignedauto_incrementprimarykey,
cat_name varchar(90)notnulldefault'',
parent_id smallintunsigned)engine myisam charset utf8;INSERTINTO`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);CREATETABLE`result`(`name`varchar(20)DEFAULTNULL,`subject`varchar(20)DEFAULTNULL,`score`tinyint(4)DEFAULTNULL)ENGINE=MyISAM DEFAULTCHARSET=utf8;insertinto result
values('张三','数学',90),('张三','语文',50),('张三','地理',40),('李四','语文',55),('李四','政治',45),('王五','政治',30);createtable a (
id char(1),
num int)engine myisam charset utf8;insertinto a values('a',5),('b',10),('c',15),('d',10);createtable b (
id char(1),
num int)engine myisam charset utf8;insertinto b values('b',5),('c',15),('d',20),('e',99);createtable m(mid int,hid int,gid int,mres varchar(10),matime date)engine myisam charset utf8;createtable t (tid int,tname varchar(20))engine myisam charset utf8;insertinto mvalues(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');insertinto tvalues(1,'国安'),(2,'申花'),(3,'布尔联队');createtable mian ( num int)engine myisam;insertinto mian values(3),(12),(15),(25),(23),(29),(34),(37),(32);createtableuser(
uid intprimarykeyauto_increment,
name varchar(20)notnulldefault'',
age smallintunsignednotnulldefault0)engine myisam charset utf8;createtable boy (hid char(1),bname varchar(20))engine myisam charset utf8;insertinto boy (bname,hid)values('屌丝','A'),('杨过','B'),('陈冠希','C');createtable girl (hid char(1),gname varchar(20))engine myisam charset utf8;insertinto girl(gname,hid)values('小龙女','B'),('张柏芝','C'),('死宅女','D');
- desc:查看表结构
- insert:插入操作
insert into user(uid,name,age) values(1,'weilei',23)
;- 添加数据 列与值严格对应 数字不必加单引号,字符串必须加单引号
insert into user(uid,name) values(2,'anti')
; – 对于年龄设置的默认值是0insert into user values(3,'weiwei',22)
; – 简写的前提是要插入所有列的数据
update操作
set sql_safe_updates =0
; – 提前加入
- update:更新操作
update user set age=18 where name='anti'
; – update:更新数据 如果where不添加指定行或者条件,则会影响所有行操作update user set name='weiling',age=124 where uid=3
; – 注意连接之间用逗号
delete操作
要删除只可能删除一行,不可能删除一行中的某个数据
deletefromuserwhere uid=1; 删除一行
delete*fromuser; 全部删除表,后果很严重
简单select
select*from t_user where id=2;select userName from t_user where password=333333; 查询密码符合条件的userName,只显示userName
5.在指定位置增加新的一列属性
altertable t_user addcolumn price varchar(10)after password
update t_user set price=100where id=1;update t_user set price=200where id=2;update t_user set price=300where id=3;altertable t_user addcolumn count varchar(10)after price;update t_user set count=1where id=1;update t_user set count=2where id=2;update t_user set count=3where id=3;altertable t_user addcolumn 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;altertable t_user addcolumn cat_id intafter phone;update t_user set cat_id=5where id=1;update t_user set cat_id=6where id=2;update t_user set cat_id=5where id=3;
查询模型
列是变量,变量可以计算 where是表达式,值为真假
select userName from t_user where password=222222;select*from t_user where1;where后面接的是表达式,1为真,所以会显示所有的数据
select id,userName,password+1from t_user where1; 列是变量,可以计算。在原来的password基础上+1
select userName from t_user where password=222222or password=333333;select userName from t_user where password in(222222,333333); 如果不用or也可以用in进行操作
select*from t_user where price >=99and price2; 取出第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():统计数字相加的总数
selectavg(price)from t_user; 求平均价格
select cat_id,avg(price)from t_user groupby cat_id;group按照cat_id进行分组
select cat_id,max(price)from t_user groupby 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可以读取内存中的结果
创建新表
insertinto grade2 values(1,'张三','数学',90,3);insertinto grade2 values(2,'张三','语文',50,5);insertinto grade2 values(3,'张三','地理',40,7);insertinto grade2 values(4,'李四','语文',55,1);insertinto grade2 values(5,'李四','数学',45,6);insertinto grade2 values(6,'王五','政治',30,2);insertinto grade2 values(7,'赵六','政治',90,4);insertinto grade2 values(8,'赵六','语文',80,8);
– 查询两门及两门以上不及格同学的平均成绩
– 思路:先统计每位同学不及格总共的门数,然后利用having统计符合条件的同学的平均成绩
select name,(sum(score=2;
9.order by:进行排序
asc:升序 desc:降序
select name,subject,score from grade orderby score;select name,subject,score from grade orderby score desc;select name,subject,score,num from grade2 orderby score;-排序之后还可以再次进行排序 多列排序
:限制取出条目:类似于pytohn中的head 取出多少个数据 有两个参数:前面参数代表 按照排序从第几个数据开始,后一个参数代表取出的数据个数
select*from grade2 orderby score limit2,3;
11.子句的查询陷阱
5种子句是有严格的顺序,where,group by,having,order by,limit 引出子查询
型子查询
–查询成绩最高的分数
select*from grade2 orderby score desclimit0,1;
select*from grade2 where score=100;selectmax(score)from grade2
select*from grade2 where score=(selectmax(score)from grade2);
型子查询
select name,score from(select*from grade2 orderby score)as tmp orderby score desc;
子查询 15.新手1+N查询模式
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 innerjoin girl on boy.hid=girl.hid;
16.左连接及右连接查询
左连接以左边数据为主,查询右边相关数据,查不到的补Nullselect boy.hid,boy.bname,girl.hid,girl.gname from boy leftjoin girl on boy.hid=girl.hid;
右连接以右边数据为主,查询左边相关数据,查不到的补Nullselect boy.hid,boy.bname,girl.hid,girl.gname from boy rightjoin girl on boy.hid=girl.hid;
select goods_id,cat_name,goods_name,shop_price from goods leftjoin category on goods.cat_id=category.cat_id;
select goods_id,cat_name,goods_name,shop_price from goods leftjoin category on goods.cat_id=category.cat_id where goods.cat_id=4;
17.union 把2条或者多条sql的查询结果合并成一个结果集 可以从一张表,也可以从多张表进行合并 需要注意:使用union需要满足各语句取出的列数相同,但是列名不一定要相同,列名称会使用第一条sql的列名称为准
select*from a unionselect*from b;
select*from a unionallselect*from b;
select goods_id,cat_id,goods_name,shop_price from goods where cat_id=4unionselect 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;
语言之DDL部分@数据定义语言【建库、建表】–“总经理”
1.创建表table
建"表"过程就是申明数据库中各个"列"的过程
creat table_name (列名 列类型 [列属性 列默认值])ENGINE= 存储引擎 defaultcharset=字符集;
列的类型知识: 数值型:整型、浮点型、定点型 整型列: 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属性【无符号】修饰;
createtable test2(
num1 tinyint)insertinto test2 values(255); 新创建一个表,直接插入255是不能成功的,因为默认范围是-128~127
altertable test2 addcolumn num2 tinyintunsignedafter num1;insertinto test2 values(120,255); 我们新申请了一个列num2,并且用unsigned定义,这时候就可以插入255,范围是0~255altertable test2 addcolumn num3 tinyint(4) zerofill after num2;insertinto test2 values(12,28,7);insertinto 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)==>存正确 总位数为3,小数点后面2位 double:和float一样,唯一区别是范围比float大。
定点列decimal[整数部分和小数部分分开来存储的] 浮点数是有精度损失的!定点列更准确 create table t4( salary1 double(9,2), salary2 decimal(9,2) ) insert into t4 values(); double浮点型显示,定点列显示 所以浮点型是有损失的 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是什么都没有,是不存在】 的索引效果不高 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:【处理快-相对不安全-不支持事务】 –说明书[声明表结构的表具体语句] –数据内容 –目录[索引文件] 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,intervalint keyword)返回日期date加上间隔时间int的结果(int必须按照关键字进行格式化),如:selectdate_add(current_date,interval6month);
date_format(date,fmt) 依照指定的fmt格式格式化日期date值
date_sub(date,intervalint keyword)返回日期date加上间隔时间int的结果(int必须按照关键字进行格式化),如:selectdate_sub(current_date,interval6month);
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 fromcurrent_date);select extract(day_second fromcurrent_date);select extract(hour_minute fromcurrent_date);
返回两个日期值之间的差值(月数):select period_diff(200302,199802);
在mysql中计算年龄:
select date_format(from_days(to_days(now())-to_days(birthday)),'%y')+0as age from employee;
这样,如果brithday是未来的年月日的话,计算结果为0。 下面的sql语句计算员工的绝对年龄,即当birthday是未来的日期时,将得到负值。
select date_format(now(),'%y')- date_format(birthday,'%y')-(date_format(now(),'00-%m-%d')如果第一个参数不是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(1100,‘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>selectcase'green'when'red'then'stop'when'green'then'go'end;selectcase9when1then'a'when2then'b'else'n/a'end;selectcasewhen(2+2)=4then'ok'when(2+2)4then'not ok'end asstatus;select name,if((isactive =1),'已激活','未激活')as result fromuserlogininfo;select fname,lname,(math+sci+lit)as total,casewhen(math+sci+lit)“同生共死”!【MyISAM不支持事务】 例如:A"打账"500给B,打完之后A减少500,B增加500!如果这两个动作有一个没完成则整个打账过程取消失败–[原子性]
2.如何启用事务? start transaction; 3.如何结束事务? commit; 4.如何撤销事务?【回滚事务】 rollback;
事务的中间状态是不可见的–隔离性 事务发生结束了之后是不能恢复的–持久性 事务之前和之后它们的业务逻辑上要保持一致!两人总账额度9000,相互转帐后依然是9000 – 一致性
总结
对于初学者来说掌握视频中所提及的基础语法已经满足日常开发中的基本需要。如果在上述基础已经完全掌握的情况下,可以再继续进行触发器等高阶知识点的学习,最好循序渐进,不要囫囵吞枣。