MYSQL学习笔记(DDL[数据定义]DML[数据操作]DQL[数据查询])
Posted il_持之以恒_li
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MYSQL学习笔记(DDL[数据定义]DML[数据操作]DQL[数据查询])相关的知识,希望对你有一定的参考价值。
前言:也不知道是大几做的mysql数据库学习笔记了,今天拿来分享一下!
1. 数据定义语言(DDL)
1.创建数据库:creat database 数据库名 character set utf8;
2.修改数据库:
3.创建表:
- 先进入某个数据库; use 数据库名称;
- 输入建表的命令:
create table 表名列名1 列的类型【约束】
列名2 列的类型【约束】
列名3 列的类型【约束】
列名4 列的类型【约束】
4.常用的命令
- 展示表中的信息:desc 表的名称;
- 添加一列:alter table 表名 add 列名 数据类型
- 修改一个字段的类型:alter table 表名 modify 字段名 数据类型;
- 删除一列:alter table 表名 drop 字段名;
- 修改表名:rename table 原表名 to 新的表名;
- 修改表达字符集:alter table 表名 character set gbk();
- 查看表的创建信息;show create table 表名;
- 修改列名:alter table 表名 change 原列名 新列名 数据类型;
- 删除表:drop table 表名;
2. 数据操作语言(DML)
对表中的数据进行增删改的操作;
常用命令如下:
(1)查询表中的数据:select * from表名;或 select * from 表名\\G; (这个应该是数据查询)
(2)插入操作:insert into 表名 (列名1,列名2,、、、)values (值1,值2,、、、);
(3)批量插入:insert into 表名(列名1,列名2,、、、) values (值1,值2,、、、),(值1,值2,、、、);
(4)更新操作:update 表名 列名1=列值1,列名2=列值2,、、、where 列名1=值1,、、、;
(5)
1.修改数据库密码: update mysql.user set authentication_string=password('12345') where user='root' and Host ='localhost';
刷新:flush privileges;
2.mysqladmin -u root -p password 新密码;
(6)删除操作:
1.delete from 表名 where(条件);
2.turncate table 表名;
两者之间的区别:delete 删除表中的数据,表的结构还在;删除的数据可以找回;
turncate删除是把表直接drop掉,然后再创建一个同样的新表。删除的数据不能找回。执行速度比delete快;
3. 数据查询语言(DQL)
1.查询所有列:select * from 表名;
2.查询指定列的数据:select 列名1,列名2、、、from 表名;
3.条件查询:运行符和关键字
(1)=(等于),!=,<>,<,>,<=,>=
(2)between、、、and 值在什么范围之内;
(3)in(set)固定范围内的
(4)is null 为空,is not null 不为空
(5)and 和
(6)or 或
(7)not 非
4.模糊查询:
(1)任意一个字符'_';
(2)任意个字符‘%’;
如:select * from where name like 'M%';
查询name中以M开头后面任意个字符
5.去重操作:
select distinct name from student;
去除name中重复的字符串
【注】把查询字段的结果进行运算,必须都是数据型
(1)select *,字段1+字段2 from 表名;
(2)列有很多记录值为null,因为任何东西与NULL相加的结果还是NULL,所以运算结果可能会出现NULL。
select *,ifnull(age,0)+ifnull(score,0) form student;
如果表student中age为空,则age=0,score亦然;
6.聚合函数:
(1)count函数:统计不为null的函数;
(2)sum函数;
(3)avg函数;
(4)max函数;
(5)min函数;
3.1 复杂查询语句
3.1.1 分组查询
将查询结果按照一个或多个字段进行分组,字段值相同的为一组;
分组使用:
1. select gender from employee group by gender;
根据gender字段进行分组,gender字段的全部值只有两个(‘男’和‘女’),所以分了两组;
当group by 单独使用时,只显示出每组的第一条记录;
所以group by单独使用时的实际意义不大;
2.group by +group_concat:group_concat(字段名)可以作为一个输出字段来使用;
表示分组之后,根据分组结果,使用group_concat()来放置每一组的某字段的值的集合
select department,group_concat('name') from employee group by department;
3.group by +having:
用来分组查询后指定一些条件来输出查询结果
having作用和where一样,但having只能用于group by
【注】having与where的区别:
- having是在分组之后进行过滤的;
- where是在分组之前进行过滤;
- having后面可以使用分组函数;
- where后面不可以使用分组函数;
- where是对分组前记录的条件,如果某行记录没有满足where子句的条件,那么这行记录不会参加分组;而having是对分组后数据的约束;
4.书写顺序:
select from where group by having order by limit;
5.执行顺序:
from where group by having select order by limit;
补充: limit的使用
格式:select * from student limit 0,5
角标从0开始;
第一个参数:表示从第几行开始;
第二个参数:表示要查几行;
分页思路:
补充概念知识:
数据完整性;
什么是数据完整性:保证用户输入的数据保存到数据库中是正确的;
如何添加数据完整性:在创建表时给表中添加约束;
完整性分类:
(1)实体完整性;
(2)域完整性
(3)引用完整性;
(1)实体完整性:
什么时实体完整性:表中的一行(一条记录)代表一个实体(entity);实体完整性的作用:标识每一行数据不重复,行级约束;
约束类型:
1.主键约束(primary key)
2.唯一约束(unique)
3.自动增长列(auto_increment)
1.主键约束:每个表中要有一个主键,数据唯一,且不能为null;
格式:
create table 表名(字段名1 数据类型 primary key,字段2 数据类型)
create table 表名(字段1 数据类型,字段2 数据类型,primary key(要设置主键的字段))
create table 表名(字段1 数据类型,字段2 数据类型,primary key(主键1,主键2));
2.唯一约束:
(1)指定列的数据不能重复;
(2)可以为null;
格式:create table 表名(字段1 数据类型,字段2 数据类型 unique);
3.自动增长列:
(1)指定列的数据自动增长;
(2)可以数据删除,还是从删除的序号继续往下;
格式:create table 表名(字段名1 数据类型 primary key auto_increment、、、);
(2)域完整性:限制此单元格的数据正确,不对照此列的其他单元格比较;域代表当前单元格;
域完整性约束:
数据类型:数值类型、日期类型、字符串类型
非空约束:create table 表名(字段名1 数据类primary key auto_increment,字段2 数据类型 unique not null);
默认值约束:(default)
(3)参照完整性:是指表与表之间对应的一种关系,通常情况下可以通过设置两表之间的主键、外键关系,或者编写两表的触发器来实现;有对应参照完整性的两张表格,在对他们进行插入、更新、删除的过程中,系统都会将被修改表格与另一张对应表格进行对照,从而阻止一些不正确的数据操作。
(1)数据库的主键和外键类型一定要一致;
(2)两个表必须是lnnoDB类型;
(3)设置参照完整性后,外键当中的内值,必须得是主键当中的内容;
(4)一个表设置当中的字段设置为主键,设置主键的为主表;
(5)创建表时,设置外键,设置外键的为子表。
代码为:
(1)ALTER TABLE score add constraint sc_st_fk foreign key(sid) references stu(id);#用表stu中的id来约束表score中的sid,使sid只能使用id中的数据;两个表存在时
(2)create table score(sid int,score int,constraint sc_st_fk foreign key(sid) references stu(id);
3.1.2.多表查询
3.1.2.1.表之间的关系;
(1)一对一;
(2)一对多;
(3)多对多;
1.创建学生表:create table teacher(tid int primary key,name varchar(50));
2.创建老师表:create table student(sid int primary key,name varchar(50));
3.创建老师与学生的关系表;create table tea_stu_rel(tid int,sid int);
4.添加外键;alter table tea_stu_rel add constraint foreign key(tid) references stu(sid);
alter table tea_stu_rel add constraint foreign key(sid) references tea(tid);
为什么要拆分表,避免大量冗余数据出现;
3.1.2.2.合并结果集;
(1)合并结果集:合并结果集就是把两个select语句的查询结果合并到一起;
(2)合并结果集的两种方式:
- nuion 合并时去除重复记录;
- union all合并时不去除重复记录;
(3)格式;union
- select * from 表1 union select * from 表2;
- select * from 表1 union all select * from 表2;
实例:
create table A(name varchar(50),score int);
create table B(name varchar(50),score int);
insert into A values('a',10),('b',20),('c',30);
insert into B values('a',10),('b',20),('d',40);
select * from A union select * from B;
select * from A union all select * from B;
(4)注意事项:被合并的两个结果:列数、列类型必须相同;
3.1.2.3.连接查询;
什么是连接查询:也可以叫跨表查询,需要关联多个表进行查询;
笛卡尔积:假设集合A={a,b},集合B={0,1,2},
则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)},可以扩展到多个集合到情况;
1.同时查询两个表,出现的结果就是笛卡尔积;select * from A,B;
2.给表起别名:select * from A B,C D;
3.如何保持数据正确:select * from stu,score where stu.id=score.sid;
根据连接方式进行分类:
1.内连接;
- 等值连接:
两个表同时出现的id号(值)才显示
select * from stu st inner join score sc on st.id=sc.sid;与多表联查约束主外键是一样,只是写法改变了;on 后面只写主外键;如果还有条件直接在后面写where,多表联查后面还有条件就直接写and; - 非等值连接:
- 多表连接;
事例:
1.(99连接法):
select st.name,sc.score,c.name from stu st,score sc,course c
where st.id=sc.sid and sc.cid=c.cid;
2.内联查询:
select st.name,sc.score,c.name from stu st
join score sc on st.id=sc.sid
join course c on sc.cid=c.cid;
2.外连接:
- 左外连接(左连接):两表满足条件相同到数据查出来,如果左边表当中有不同到数据,也把左边表当中到数据查出来;
格式:select * from stu st left outer join score sc on st.id=sc.sid; - 右外连接(右连接):两表满足条件相同到数据查出来,如果右边表当中有不同到数据,也把右边表当中到数据查出来;
格式:select * from stu st right join score sc on st.id=sc.sid; - 自然连接:连接查询会产生无用笛卡尔积,我们通常使用主外键关系等式来去除它。而自然连接无需你去给主外键等式,它会自动找到这一等式,也就是说不用去写条件;
要求:两张连接的表中列名称和类型完全一致的列作为条件,会去除相同的列;
格式:select * from stu natural join score;
3.自连接
自己连接自己,给自己起别名;
3.1.2.4.子查询:
什么是子查询:一个select语句中包含另一个完整的select语句或两个以上select,那么就是子查询语句了;
子查询出现的位置:
- where后,把select查询出的结果当作另一个select的条件值;
- from后,把查询出的结果当作一个新表;
事例:
(1)select ename,deptno from emp where deptno=(select deptno from emp where ename='项羽');
(2)select ename,deptno from (select ename,deptno,salary from emp) s where s.salary>2000;
3.2 常用函数
函数介绍:事先提供好的一些功能可以直接使用,函数可以用在select语句及其子句,也可以用在update,delete语句当中;
函数分类;
-
字符串函数:
- concat(s1,s2,、、、,sn):将传入到字符串连接成一个字符串,任何字符串与null字符串连接都是null;
- insert(str,x,y,instr)将字符串str从x位置开始,y个字符长的子串替换为指定到字符;
- upper(),lower():英文字符转大小写
- left(str,x)和right(str,x):分别返回字符串最左边到x个字符和最右边的x个字符,如果第二个参数为null,那么不返回任何字符;
- lpad(str,n,pad)和rpad(str,n,pad):用字符串pad对str最左边或最右边进行填充,直接到长度为n个字符长度;
- ltrim(str)和rtrim(str):去掉字符串当中最左侧和最右侧的空格;
- trim(str):去掉字符串左右的空格;
- repeat(str,n):返回str重复x次的结果;
- replace(str,a,b):用字符串b替换字符串str中所有出现到字符串a;
- substring(str,x,y):返回字符串str从第x字段起长度为y的字符串;
-
数值函数;
- abs(x):返回x的绝对值;
- ceil(x):小数不为0进行向上取整;
- floor(x):小数不为0进行向下取整;
- mod(x,y):返回x除y的余数;
- rand():取0到1之间的随机数;
-
日期与时间函数;
- curdate():返回当前时间,只包含年月日;
- curtime():返回当前时间,只包含时分秒;
- unix_timestamp:返回当前日期的时间戳;
- from_unixtime(unixtime):将一个时间戳转换成一个日期;
- week(date):返回当前是一年的第几周;
- year(date):返回所给日期是哪一年;
- hour(time):返回当前时间的小时;
- minute(time):返回当前时间的分钟;
- date format(date,fmt):按字符串格式化日期date值;
- date_add(date,interval expr type):计算日期间隙;
- datediff(date1,date2):计算两个日期的差;
- now():返回当前时间;
-
流程函数;
- if(value,t,f):如果value是真,返回t,否则返回f;
- ifnull(value1,value2):如果value1不为空,返回value1,否则返回value2;
- case when then end;
-
其他函数;
- datebase():返回当前数据库
- version():返回当前数据库的版本;
- user():返回当前用户名;
- password(str);
- md5():返回str的md5值;
4.事务
不可分割的操作,假设该操作有abcd四个步骤.若abcd四个步骤都成功完成,则认为事务成功;若abcd中任意一个步骤操作失败,则认为事务失败;每条sql语句都是一个事务;事务只对DML语句有效,对于DQL无效;
(1)事务的ACID:
- 原子性(Atomicity)原子性是指事务包含的操作要么全部成功,要么全部失败回滚;
- 一致性(Consistency):一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后必须处于一致性状态。
- 隔离性(Isolation):
- 持久性(Durability):
(2)事务的使用:
- 开启事务:start transaction;
- 回滚操作:rollback:
- 提交事务:commit;
所有语句全部执行完毕,没有发生异常,提交事务,更新到数据库当中;
(3)执行流程:
(4)事务的并发过程:
- 脏读;解决办法:Read committed!读提交,能解决脏读问题;
- 不可重复读;
- 重复读:一个事务范围内两个相同的查询却返回了不同的数据;
解决办法:Repeatable read; - 幻读;解决办法:Serializable;
- 对应关系
事务隔离级别 | 读未提交(read-uncommitted) | 不可重复读(read-committed) | 可重复读(repeatable-read) | 串行(Serializable) |
---|---|---|---|---|
脏读 | 是 | 否 | 否 | 否 |
不可重复读 | 是 | 是 | 否 | 否 |
幻读 | 是 | 是 | 是 | 否 |
(5)事务隔离级别:
- Read uncommitted :就是一个事务可以读取另一个未提交事务的数据;
- .Read committe:一个事务要等到另一个事务提交后才可以读取数据;
- Repeatable read:
- Serializable:
(6)查看隔离级别:select@@global.tx_isolation,@@tx_isolation;
(7)设置隔离级别:1.全局的:set global transaction isolation level read committed;
5. 权限
权限:限制一个用户能够做什么事情,在MySQL中,可以设置全局权限,指定数据库权限,指定表权限,指定字段权限;
权限:
- create 创建数据库、表或索引权限;
- drop 除数据库或表权限;
- alter alter更改表,比如添加字段、索引等;
- delete 删除数据权限;
- index 索引quanxian
- insert 插入权限
- select 查询权限
- update 更新权限
- create view 创建视图权限
- execute 执行存储过程权限
(1)创建用户:create user '用户名'@'localhost'identified by '密码';
(2)删除用户:drop user 用户名称;
(3)分配权限:grant 权限(columns)on 数据库对象 to 用户 identified by '密码' with grant option;
(4)查看权限:
show grants;
show grants for root@localhost;
(5)删除权限:revoke 权限 on 数据库对象 from 用户;
6. 视图
视图是一个虚拟表,其内容由查询定义;同真实的表一样,视图包含一系列带有名称的列和行数据;
行和列数据来自定义视图的查询所引用的表,并且在引用视图时动态生成;简单的来说视图是由select结果组成的表;
-
视图的特性:视图是对若干张基本表的引用,一张虚表,查询语句执行的结果;
不存储具体的数据(基本表数据发生了改变,视图也会跟着改变);
可以跟基本表一样,进行增删改查操作(增删改查有条件限制); -
视图的作用:
- 安全性:创建一个视图,定义好该视图所操作的数据。之后将用户权限与视图绑定;这样的方式是使用到了一个特性;grant语句可以针对视图进行授予权限。
- 查询性能提高。
- 提高了数据的独立性;
-
创建视图;create view 视图名 as ( );
-
修改视图:create or replace view 视图名 as select […]from[…]
-
删除视图:drop view 视图名;
-
视图机制:
- 替代式:操作视图时,视图名直接被视图定义给替换掉;
select * from (select * from student where age=18) stu; - 具化式:mysql先得到了视图执行的结果,该结果形成一个中间结果暂时存在内存中。外面的select语句就调用了这些中间结果(临时表);
(select * from student where age =18) as stu;
select * from stu; - 具化式与替换式区别:替换方式,将视图公式替换后,当成一个整体sql进行处理了;具化式方式,先处理试图结果,后处理外面的查询需求;
- 替代式:操作视图时,视图名直接被视图定义给替换掉;
-
视图不可更新部分:
- 聚合函数;
- distinct关键字;
- group by子句;
- having子句;
- union运算符;
- from子句中包含多个表;
- select语句中引用了不可更新视图;
- 只要视图当中的数据不是来自于基表,就不能够直接修改;
7.存储过程
一组可以编程的函数,是为了完成特定功能的sql语句表;存储过程就是具有名字的一段代码,用来完成一个特定的功能;创建的存储过程保存在数据库的数据字典中;
1.为什么要用存储过程:将重复性很高的一些操作,封装到一个存储过程中,简化了对这些sql的调用;批量处理;统一接口,确保数据的安全;相对于oracle数据库来说,MySQL的存储过程相对功能较弱,使用较少;
2.存储过程的创建和调用:
1.delimiter $$:它与存储过程语法无关;
delimiter语句将标准分隔符-分号(;)更改为:$$
因为我们想将存储过程作为整体传递给服务者;
而不是让mysql工具一次解释每一条语句;
告诉mysql解释器,该段命令是否已经结束了,mysql是否执行了。默认情况下,delimiter是分号。在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令,但有时候,不希望MySQL这么做,在为可能输入较多的语句,且语句中包含有分号。使用delimiter $$,这样只有当$$出现之后,mysql解释器才会执行这段语句;
2.存储过程的创建: create procedure 名称()
begin
语句
end $$
调用存储过程:call 名称();
3.查看存储过程:
1.查看所有存储过程: show procedure status;
2.查看指定数据库中的存储过程:show procedure status where db='数据库名称':
3.查看指定存储过程源代码:show create procedure 存储过程名;
4.删除存储过程:drop procedure 存储过程名;
5.存储过程变量:
在存储过程中声明一个变量;
使用declare语句:
(1)declare 变量名 数据类型(大小) default 默认值;
(2)可以声明一个名为total_sale的变量,数据类型为int,默认值为0;
(3)声明共享相同数据类型的两个或多个变量:
declare x,y int default 默认值;
分配变量值:要为变量分配一个值,可以使用set语句;
使用select into语句将查询的结果分配给一个变量;
变量的范围:如果在存储过程中声明一个变量,那么当达到存储过程的end语句时,它将超出范围,因此在其他代码块中无法访问;
6.存储过程参数:
(1)三种类型
in
out
inout
(2)定义参数:create produce name(模式,参数名称 数据类型(大小))
7.存储过程语句:
if语句:
(1)if experssion then
statements;
end if;
(2)if experssion then
statements;
else
else-statements;
end if;
case语句:case case_experssion
when when_experssion_1 then commands
when when_experssion_2 then commands
...
else commands
end case;
循环:(1)while experssion DO
statements
end while;
(2)repeat
statements;
union exprssion
end repeat;
13.索引;
(1)什么是索引:索引用于快速找出在某个列中有一定值得行;
不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行;
表越大,查询数据所花费的时间就越多;
如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据文件;
而不必查看所有数据,那么将会节省很大一部分时间;
(2)索引的优势和劣势:通过索引对数据进行排序,降低数据排序的成本,降低了CUP的消耗;
实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占空间的;
虽然索引大大提高了查询的速度,同时却会降低更新表的速度。
(3)索引的分类:
1.单值索引:即一个索引只包含单个列,一个表可以有多个单列索引;
2.唯一索引:索引列的值必须唯一,但允许有空值;
3.复合索引:一个索引包含多个列,index Multildx(id,name,age);
4.全文索引;
5.空间索引:空间索引是对空间数据类型的字段建立的索引;
(4)索引操作;
1.创建索引:create index 索引名称 on table();
2.删除索引:drop index 索引名称 on 表名
3.查看索引:show index from 表名;
4.自动创建索引:在表上定义了主键时,会自动创建一个对应的唯一索引;在表上定义一个外建时,会自动创建一个普通索引;
(5)explain;
(6)索引结构:btree索引hash索引;
(7)那些情况下需要创建索引:
1.主键自动建立唯一索引;
2.频繁作为查询条件的字段应该创建索引;
3.查询中与其他表关联的字段,外键关系建立索引;
4.频繁更新的字段不适合建立索引,因为每次更新不单单是更新了记录还会更新索引;
5.where条件里用不到的字段不创建索引;
6.查询中排序的字段,排序的字段若通过索引去访问将大大提高排序速度;
7.查询中统计或者分组字段;
(8)那些情况下不需要创建索引:
1.表记录太少;
2.经常增删改的表;
3.如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果;
以上是关于MYSQL学习笔记(DDL[数据定义]DML[数据操作]DQL[数据查询])的主要内容,如果未能解决你的问题,请参考以下文章