MySQL从入门到精通(第一篇):SQL语句以及数据库设计,结合多篇文章

Posted 后端漫漫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL从入门到精通(第一篇):SQL语句以及数据库设计,结合多篇文章相关的知识,希望对你有一定的参考价值。

mysql目录


参考文章:数据库系统学习
参考文章:非关系型数据库讲解
参考文章:mysql学习(详细)
参考文章:函数依赖
参考文章1:范式
参考文章2:范式

一、数据库入门

1. 数据管理技术的三个阶段

  • 人工管理阶段:在计算机出现之前,人们主要利用纸张和计算工具(如算盘和计算尺)来进行数据的记录和计算,依靠大脑来管理和利用数据。
  • 文件系统阶段:将数据存储在计算机的磁盘上。这些数据都以文件的形式存储,然后通过文件系统来管理这些文件。
  • 数据库系统阶段:相对于文件系统来说,数据库系统实现了数据结构化。在文件系统中,独立文件内部的数据一般是有结构的,但文件之间不存在联系,因此整体来说是没有结构的。 数据库系统虽然也常常分成许多单独的数据文件,但是它更注意同一数据库中各数据文件之间的相互联系。

2. 关系型数据库与非关系型数据库

  • 关系型数据库是由多张能互相连接的表组成的数据库。
  • 非关系型数据库通常指数据以对象的形式存储在数据库中,而对象之间的关系通过每个对象自身的属性来决定。
  • 相信大家对关系型数据库已经非常了解,下面将以四大非关系型数据库讲解,来让我们看看两者区别

3. 四大非关系型数据库

简述:目前对于非关系型数据库主要有四种数据存储类型:键值对存储(key-value),文档存储(document store),基于列的数据库(column-oriented),还有就是图形数据库(graph database)。每一种都会解决相应的问题,这些问题是关系型数据库所不能解决的。而在实际应用中都会将这几种情况结合起来实现相应的功能。


在开始介绍NoSQL数据库之前,我们先来回顾一下关系型数据库,这样我们可以对非关系数据库和关系型数据库做一个深入的比较。

例如:如果你想存储一个人的信息和这个人的爱好这样的数据,你可以创建两个表:一个用来存储这个人的信息,另一个表用来存储这个人的爱好。正如你在图一中看到的,你必须有一张额外的映射表,这张表将人的信息表和爱好表建立其对应的关系。这是因为他们的关系是多对多的关系,一个人可以有多个爱好,并且多个人可能会有相同的爱好。

a. 基于列的数据库(column-oriented)

  1. 这里你就需要注意了,这种请款下你已经有一点违反关系型数据库严格遵循的标准化了,因为爱好是有重复的。
  2. 在基于行的数据库中进行查找的时候,每次都会对每一行进行遍历,不管某一列数据是否是你需要的都会进行遍历。假如你只需要生日是九月的人的数据,基于行的数据库会对这张表从上到下从左至右遍历一遍,正像下图看到的那样,最后再返回你需要的那些数据。对特定列的数据进行索引能有效的提高查找速度,但是索引每一列同样会带来额外的负载,并且数据库同样也是会遍历所有的列来取得要查找的数据。基于列的数据库会将每一列分开单独存放,当查找一个数量较小的列的时候其查找速度是很快的。

  3. 说了这么多,那应该在什么时候使用基于行的数据库,在什么时候使用基于列的数据库呢?在基于列的数据库中要想增加一列新的数据是很容易的,因为现有的那些列是不会受新增列的影响的。但是要想增加一整条记录就需要适应所有的表,防止各个表的数据之间对应关系出现错误。因此这使得基于行的数据库在事务处理的时候要优胜于基于列的数据库,因为它很好的实现了数据的实时更新。

b. 键值对存储(Key-Value Stores)

键值对中存储的数据的类型是不受限制的,可以是一个字符串,也可以是一个数字,甚至是由一系列的键值对封装成的对象等

c. 文档存储(Document Stores)

文档存储是基于键值对存储的,其结构较之于键值对存储更为复杂,可以说在键值对的基础上更深入了一步。

d. 图形数据库(Graph Database)

现在剩下的是最后一个NoSQL数据库存储类型,也是最复杂的一个,主要使用一种高效的方式来存储各个实体之间的关系。当数据之间是紧密联系的,例如社会关系、科学论文的引文抑或是资本资产定价模型等等,使用图形数据库时最好的选择。图形或者网络数据有两部分组成:

  • Node-:实体本身,在一个社会关系中可以认为是一个人。
  • Edge-:实体之间的关系。这个关系可以用一条线来表示,这条线有它自己的属性。这条线可以有方向,箭头可以表明谁是谁的上级。

如果给予足够的关系和实体类型,图形会变得非常的复杂,其发杂程度简直难以置信。

二、SQL语句学习

  1. DDL(Data Definition Language)数据定义语言
    用来定义数据库对象:数据库,表,列等。关键字:create, drop,alter 等
  2. DML(Data Manipulation Language)数据操作语言
    用来对数据库中表的数据进行增删改。关键字:insert, delete, update 等
  3. DQL(Data Query Language)数据查询语言
    用来查询数据库中表的记录(数据)。关键字:select, where 等
  4. DCL(Data Control Language)数据控制语言(了解)
    用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE 等
  5. TCL(Transition Language) :事务控制语言,用来管理事务

1. DCL数据控制语言

1.1 创建用户

  • ’alian’@'localhost’ :表示只允许本机登录
  • ’alian’@’%’ :表示任意地址登录
  • ’alian’@'192.168.0.100’ :表示只允许ip为192.168.0.100的地址登录
  • ’alian’@‘192.168..’ :表示只允许ip为192.168网段的地址登录
# 格式
create user '用户名'@'IP地址' identified WITH mysql_native_password by '密码';
flush privileges;

# 实例
CREATE USER 'alian'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;

1.2 修改用户名

rename user '用户名'@'IP地址' to '新用户名'@'IP地址';

1.3 修改密码

#切换到mysql库
use mysql;
#更新密码
UPDATE user SET password=password('新密码') WHERE user='用户名' AND host='IP地址';
#刷新权限
FLUSH PRIVILEGES;

或者

ALTER USER '用户名'@'IP地址' IDENTIFIED WITH mysql_native_password BY '新密码';
flush privileges;

或者

#普通用户登录后
SET PASSWORD=password('新密码');
FLUSH PRIVILEGES;

1.4 删除用户

#注意这里的IP地址,一个用户可能会有多个
drop user '用户名'@'IP地址';
#比如
drop user 'Alian'@'192.168.0.100';

1.5 授权

grant 权限1, 权限2, 权限3,,权限n on 数据库名.表名 to 用户名@地址;

数据库名.表名

  • . 表示任意库的任意表(不建议)
  • mysql.* 表示mysql库的任意表
  • mysql.user 表示mysql库的user表

用户名@地址

  • ’alian’@'localhost’ :表示只允许本机登录
  • ’alian’@’%’ :表示任意地址登录
  • ’alian’@'192.168.0.100’ :表示只允许ip为192.168.0.100的地址登录
  • ’alian’@‘192.168..’ :表示只允许ip为192.168网段的地址登录

实例

#把数据库的所有库的所有权限都给alian,并且是任意ip地址都可以操作
grant all privileges on *.* to 'alian'@'%';
flush privileges;

#把mysql数据库的所有权限都给alian,并且是任意ip地址都可以操作
grant all privileges on mysql.* to 'alian'@'%';
flush privileges;

#把mysql数据库的user表的所有权限都给alian,并且是只能通过192.138.0.10才可以操作
grant all privileges on mysql.user to 'alian'@'192.138.0.10';
flush privileges;

#把mysql数据库的user表的(查询,插入,更新,删除)的权限都给alian,并且是任意ip地址都可以操作
grant SELECT, INSERT, UPDATE, DELETE on mysql.user to 'alian'@'%';
flush privileges;

1.6 查看权限

show grants for 'alian'@'%';

1.7 回收权限

#格式
revoke 权限1, 权限2…权限n on 数据库名.表名 from 用户名@地址;

#实例:回收用户的更新和删除mysql(默认的库)数据库的权限
revoke update,delete on mysql.user from 'alian'@'%';

2. DDL数据定义语言

2.1 操作数据库

创建

	# 创建数据库,判断不存在,再创建:
		 create database if not exists 数据库名称;
	# 创建数据库,并指定字符集
		 create database 数据库名称 character set 字符集名;

查询

	* 查询所有数据库的名称:
		 show databases;
	* 查询某个数据库的字符集:查询某个数据库的创建语句
		 show create database 数据库名称;

修改

	* 修改数据库的字符集
		 alter database 数据库名称 character set 字符集名称;

删除

	* 删除数据库
		 drop database 数据库名称;
	* 判断数据库存在,存在再删除
		 drop database if exists 数据库名称;

2.2 操作数据表

创建

create table 表名(
	列名1 数据类型1,
	列名2 数据类型2,
	....
	列名n 数据类型n
);

# 数据库类型
	1. int:整数类型		
	2. double:小数类型
	3. date:日期,只包含年月日,yyyy-MM-dd
	4. datetime:日期,包含年月日时分秒	 yyyy-MM-dd HH:mm:ss
	5. timestamp:时间错类型	包含年月日时分秒	 yyyy-MM-dd HH:mm:ss	
	6. varchar:字符串,* zhangsan 8个字符  张三 2个字符

查询

	* 查询某个数据库中所有的表名称
		 show tables;
	* 查询表结构
		 desc 表名;

修改

	1. 修改表名
		alter table 表名 rename to 新的表名;
	2. 修改表的字符集
		alter table 表名 character set 字符集名称;
	3. 添加一列
		alter table 表名 add 列名 数据类型;
	4. 修改列名称 类型
		alter table 表名 change 列名 新列别 新数据类型;
		alter table 表名 modify 列名 新数据类型;
	5. 删除列
		alter table 表名 drop 列名;

删除

	* drop table 表名;
	* drop table  if exists 表名 ;

2.3 操作数据

添加

insert into 表名(列名1,列名2,…列名n) values(1,2,…值n);

删除

delete from 表名 [where 条件]

修改

update 表名 set 列名1 =1, 列名2 =2,[where 条件];

3. DQL数据查询语言

3.1 基本语法

select
	字段列表
from
	表名列表
where
	条件列表
group by
	分组字段
having
	分组之后的条件
order by 
	排序
limit
	分页限定

3.2 条件查询

			-- 查询年龄大于20岁
			SELECT * FROM student WHERE age > 20;
			
			SELECT * FROM student WHERE age >= 20;
			
			-- 查询年龄等于20岁
			SELECT * FROM student WHERE age = 20;
			
			-- 查询年龄不等于20岁
			SELECT * FROM student WHERE age != 20;
			SELECT * FROM student WHERE age <> 20;
			
			-- 查询年龄大于等于20 小于等于30
			SELECT * FROM student WHERE age >= 20 &&  age <=30;
			SELECT * FROM student WHERE age >= 20 AND  age <=30;
			SELECT * FROM student WHERE age BETWEEN 20 AND 30;
			
			-- 查询年龄22岁,18岁,25岁的信息
			SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25
			SELECT * FROM student WHERE age IN (22,18,25);
			
			-- 查询英语成绩为null
 			SELECT * FROM student WHERE english = NULL; -- 不对的。null值不能使用 = (!=) 判断
			
			SELECT * FROM student WHERE english IS NULL;
			
			-- 查询英语成绩不为null
			SELECT * FROM student WHERE english  IS NOT NULL;
			-- 查询姓马的有哪些? like
			SELECT * FROM student WHERE NAME LIKE '马%';
			-- 查询姓名第二个字是化的人
			SELECT * FROM student WHERE NAME LIKE "_化%";
			
			-- 查询姓名是3个字的人
			SELECT * FROM student WHERE NAME LIKE '___';
			
			-- 查询姓名中包含德的人
			SELECT * FROM student WHERE NAME LIKE '%德%';

3.3 排序查询

#查询员工信息, 要求工资从低到高排序(ASC可省略)
SELECT * FROM 表名 ORDER BY salary ASC;

#查询员工信息, 要求工资从高到低排序
SELECT * FROM 表名 ORDER BY salary DESC;

3.4 聚合函数

聚合函数的计算,排序null值

COUNT()函数和GROUP BY关键字一起来计算不同分组中的记录总数
select o_num count(f_id) from orderitems group by o_num;

#SUM()可以与GROUP BY一起使用,来计算每个分组的总和
select o_num,sum(quantity) as items_total from orderitems group by o_num;

#AVG()可以与GROUP BY一起使用,来计算每个分组的平均值
select s_id,AVG(f_price) as avg_price from fruits group by s_id;

#MAX()也可以和GROUP BY关键字一起使用,求每个分组中的最大值。
select s_id,max(f_price) as max_price from fruits group by s_id;

#MIN()也可以和GROUP BY关键字一起使用,求出每个分组中的最小值。
select s_id,min(f_price) as min_price from fruits group by s_id;

3.5 分组查询

  • where 在分组之前进行限定,如果不满足条件,则不参与分组。
  • having在分组之后进行限定,如果不满足结果,则不会被查询出来
  • where 后不可以跟聚合函数
  • having可以进行聚合函数的判断。
-- 按照性别分组。分别查询男、女同学的平均分
	SELECT sex , AVG(math) FROM student GROUP BY sex;
	
	-- 按照性别分组。分别查询男、女同学的平均分,人数
	SELECT sex , AVG(math),COUNT(id) FROM student GROUP BY sex;
	
	--  按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组
	SELECT sex , AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex;
	
	--  按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组,分组之后。人数要大于2个人
	SELECT sex , AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex HAVING COUNT(id) > 2;
	
	SELECT sex , AVG(math),COUNT(id) 人数 FROM student WHERE math > 70 GROUP BY sex HAVING 人数 > 2;

3.6 分页查询

# 语法:limit 开始的索引,每页查询的条数;
SELECT * FROM student LIMIT 0,3;

4. 约束

主键约束:primary key
非空约束:not null
唯一约束:unique
外键约束:foreign key
默认值 :Default


4.1 非空约束

# 创建表时,添加非空约束
CREATE TABLE stu(
	id INT,
	NAME VARCHAR(20) NOT NULL -- name为非空
);

# 创建表后,添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;

# 删除name的非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);

4.2 唯一约束

# 创建表时,添加唯一约束
CREATE TABLE stu(
	id INT,
	phone_number VARCHAR(20) UNIQUE -- 添加了唯一约束

);

# 在创建表后,添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;

# 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;

4.3 主键约束

# 创建表时,添加主键约束
create table stu(
	id int primary key,-- 给id添加主键约束
	name varchar(20)
);

# 创建完表后,添加主键
ALTER TABLE stu MODIFY id INT PRIMARY KEY;

# 删除主键:错误 alter table stu modify id int ;
ALTER TABLE stu DROP PRIMARY KEY;

4.4 自动增长约束

# 创建表时,添加自动增长约束
create table stu(
	id int primary key auto_increment,-- 给id添加主键约束
	name varchar(20)
	);

# 创建表后,添加自动增长约束
ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;

# 删除自动增长
ALTER TABLE stu MODIFY id INT;

4.5 外键约束

在创建数据表时添加约束。
下面语句执行成功之后,在表 tb_emp6 上添加了名称为 fk_emp_dept1 的外键约束,外键名称为 deptId,其依赖于表 tb_dept1 的主键 id。

mysql> CREATE TABLE tb_dept1
    -> (
    -> id INT(11) PRIMARY KEY,
    -> name VARCHAR(22) NOT NULL,
    -> location VARCHAR(50)
    -> );
mysql> CREATE TABLE tb_emp6
    -> (
    -> id INT(11) PRIMARY KEY,
    -> name VARCHAR(25),
    -> deptId INT(11),
    -> salary FLOAT,
    -> CONSTRAINT fk_emp_dept1
    -> FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
    -> );

在修改表时添加外键约束

mysql> ALTER TABLE tb_emp2
    -> ADD CONSTRAINT fk_tb_dept1
    -> FOREIGN KEY(deptId)
    -> REFERENCES tb_dept1(id);

删除外键约束

mysql> ALTER TABLE tb_emp2
    -> DROP FOREIGN KEY fk_tb_dept1;

三、候选码、主码、主属性

  • 候选码: 若关系中的某一属性组的值能唯一地标识一个元组,而其子集不能,则称该属性组为候选码。
  • 主码: 若一个关系中有多个候选码,则选定其中一个为主码。
  • 主属性: 所有候选码的属性称为主属性。不包含在任何候选码中的属性称为非主属性或非码属性。

四、函数依赖、部分函数依赖、完全函数依赖、传递函数依赖、多值依赖

1. 函数依赖

有一个关系模式S(Sno,Sname,Sage):如果知道了一个学生的学号Sno,那我就能确定他的姓名Sname和年龄Sage。

2. 完全依赖

如果我想知道某位学生的某一门课的成绩Grade,那我必须得同时知道他的学号Sno和课程号Cno。
但如果我只知道一部分信息,比如他的Sno或者Cno可以吗?答案是不行的!此时称Y[Grade]完全依赖于X[Sno,Cno]。

3. 部分函数依赖

如果我想知道某位学生的姓名Sname,那我知道他的学号Sno就可以了。也就是说Y[Sname]只函数依赖于X[Sno,Cno]中的子集x[Sno],此时称Y部分函数依赖于X。

4. 传递函数依赖

有一个关系模式S(Sno,Sdept,Mname)
如果我知道了一个学生的学号Sno,那我就能知道他所在的系Sdept。(因为理论上一个学生只属于一个系)
如果我知道了某一个系Sdept,那么我就能知道这个系的系主任的姓名Mname。(一个系只有一个正的系主任,别杠,你赢了。)
也就是说,我知道了一个学生的学号Sno,其实我就知道了他所在系的系主任的姓名Mname。但这个过程中,他们是不存在直接函数依赖的,我需要通过系名称Sdept作为一个桥梁去把二者联系起来的。

5. 多值依赖

定义: 一个关系,至少存在三个属性(A、B、C),才能存在这种关系。对于每一个A值,有一组确定的B值和C值,并且这组B的值独立于这组C的值。
实例: 比如我们建立课程教师和教材的模型,我们规定,每门课程有对应的一组

以上是关于MySQL从入门到精通(第一篇):SQL语句以及数据库设计,结合多篇文章的主要内容,如果未能解决你的问题,请参考以下文章

js教程--从入门到精通 第一篇 js的前世今生以及js中基本数据类型和引入方式

MySQL从入门到精通高级篇MySQL的SQL语句执行流程

MySQL从入门到精通高级篇MySQL的SQL语句执行流程

MySQL从入门到精通50讲-DDL语句详解

Android开发 Android Studio2.0 教程从入门到精通Windows版 - 入门篇

网络安全从入门到精通 (第五章-3) MSSQL反弹注入