1.数据库
1.1 什么是数据库?
所谓的数据库就是指理数据的存储和管理仓库
扩展内容1:数据库有哪些分类?(了解)///////
早期: 层次式数据库、网络型数据库
现在:关系型数据库、非关系型数据库
1. 数据库的英文单词: DataBase 简称 : DB 2. 数据库的特点: **1. 持久化存储数据的。其实数据库就是一个文件系统 2. 方便存储和管理数据 3. 使用了统一的方式操作数据库 — SQL 3.一个数据库服务器中可以创建多个数据库(dataBases),每一个数据库都是一个单独的仓库。**
1.2什么是关系型数据库?
1.3什么是数据库服务器?
数据库服务器就是一个软件(比如mysql软件)将数据库软件安装在电脑上,当前电脑就是一个数据库服务器,可以对外提供存取数据的服务。
1.4什么是表?
一个数据库中可以创建多张表,每张表用于存储一类信息(用户表存放用户信息,部门表存放部门信息)。
1.5什么表记录?
一张表中可以包含多行表记录,每一行表记录用于存储某一条具体的数据。
2.SQL
2.1.什么是SQL?
Structured Query Language(SQL):结构化查询语言
1.使用SQL可以操作数据库、表、表记录
(1)创建数据库、删除数据库、修改数据库、查询数据库
(2)创建表、删除表、修改表、查询表
(3)新增表记录、删除表记录、修改表记录、查询表记录
使用SQL也可以操作存储过程/视图/索引等。
提示:SQL是一个标准通用的操作关系型数据库的语言(普通话),每个数据库厂商为了增强自己数据库的功能,都提供了支持自己数据库的语言,称之为数据库的方言。方言不通用!
2.连接MySQL
(1)连接mysql服务器:mysql -uroot -p密码
-u:后面的root是用户名,这里使用的是超级管理员root;
-p:(小写的p)后面的root是密码,这是在安装MySQL时就已经指定的密码;
(2)连接mysql服务器并指定IP和端口:mysql -uroot -proot -h127.0.0.1 -P3306
-h:后面给出的127.0.0.1是服务器主机名或ip地址,可以省略的,默认连接本机;
-P:(大写的P)后面的3306是连接端口,可以省略,默认连接3306端口;
(3)退出客户端命令:**quit或exit或 \q**
2.2SQL通用语法
1. SQL 语句可以单行或多行书写,以分号结尾。<br /> 2. 可使用**空格和缩进**来增强语句的可读性。<br /> 3. MySQL 数据库的 SQL 语句不区分大小写,关键字建议**使用大写**。<br /> 4. 3 种注释<br /> * 单行注释: -- 注释内容 或 # 注释内容(mysql 特有) <br /> * 多行注释: /* 注释 */ <br />5.在cmd中连接mysql服务器之后,在书写SQL语句时,可以通过 \c 取消当前语句的执行。
2.3SQL分类
1) **DDL(Data Definition Language)数据定义语言**<br /> 用来定义数据库对象:数据库,表,列等。关键字:create, drop,alter 等<br /> 2) **DML(Data Manipulation Language)数据操作语言**<br /> 用来对数据库中表的数据进行增删改。关键字:insert, delete, update 等<br /> 3) **DQL(Data Query Language)数据查询语言**<br /> 用来查询数据库中表的记录(数据)。关键字:select, where 等<br /> 4) **DCL(Data Control Language)数据控制语言(了解)**<br /> 用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE 等
2.3.1DDL:操作数据库、表
1.1 操作数据库:CRUD
1. C(Create):创建
创建数据库:
* create database 数据库名称;
eg: create database mydb1; -- 创建mydb1数据库
创建数据库,判断不存在,再创建**:**
* create database if not exists 数据库名称;
create database if not exists mydb1;
创建数据库,并指定字符集
* create database 数据库名称 character set 字符集名;
eg: create database mydb1 character set utf8;
create database mydb2 charset utf8;
* 练习: 创建db4数据库,判断是否存在,并制定字符集为gbk
* create database if not exists db4 character set gbk;
2. R(Retrieve):查询
查询所有数据库的名称:
* show databases;
**查询某个数据库的字符集**:查询某个数据库的创建语句
* show create database 数据库名称;
3. U(Update):修改
修改数据库的字符集
* alter database 数据库名称 character set 字符集名称;
eg: alter database mydb1 character set gbk;
alter database mydb1 charset gbk;
4. D(Delete):删除
删除数据库
* drop database 数据库名称;
drop database mydb1;
判断数据库存在,存在再删除
* drop database if exists 数据库名称;
drop database if exists mydb1;
5. 使用数据库
查询当前正在使用的数据库名称
* select database();
使用数据库
* use 数据库名称;
use mydb1;
1.2 操作表(CRUD)
**1. C(Create):创建**<br /> 1. 语法: create table 表名( <br />列名1 数据类型1, <br />列名2 数据类型2, <br />.... <br />列名n 数据类型n );<br /> 注意:最后一列,不需要加逗号(,)<br /> 数据库类型:
1.** ****int**:整数类型
* age int,
2. **double**:小数类型
* score double(5,2)
3. **date**:日期,只包含年月日,yyyy-MM-dd
4. **datetime**:日期,包含年月日时分秒 yyyy-MM-dd HH:mm:ss
5. **timestamp**:时间戳类型 包含年月日时分秒 yyyy-MM-dd HH:mm:ss
- 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值
- timestamp最大表示2038年,而datetime范围是1000~9999
- timestamp在插入数据、修改数据时,可以自动更新成系统当前时间(后面用到时再做讲解)
6. **varchar(n):变长字符串,最长不超过65535个字节,n表示字符数,一般超过255个字符,会使用text类型**
* name varchar(20):姓名最大20个字符
* zhangsan 8个字符 张三 2个字符。
- iso8859-1码表:一个字符占用1个字节 n = 65535
- utf8码表:一个中文汉字占用3个字节 n = 65535/3
- GBK码表:一个中文汉字占用2个字节,n= 65535/2
7.char(n):字符串定长** 最长255个字符,n表示字符数 定长:是当插入的值长度小于指定的长度时,剩余的空间会用空格填充。(这样会浪费空间)
8.大文本(长文本)类型 text** 最长65535个字节,一般超过255个字符列的会使用text。
辨析:
(1)char(n)在保存数据时,长度小于指定的长度n,会造成空间浪费,但是char类型的存储速度较varchar和text快。
因此char类型适合存储长度固定的数据,这样就不会有空间浪费,存储效率比后两者还快!
(2)varchar(n)保存数据时,按数据的真实长度存储,剩余的空间可以留给别的数据用,因此varchar不会浪费空间。
因此varchar适合存储长度不固定的数据,这样不会有空间的浪费。
(3)text是大文本类型,一般文本长度超过255个字符,就会使用text类型存储。
eg:创建表:
create table student(
id int, --学号
name varchar(32),--姓名
age int ,--年龄
score double(4,1),--分数
birthday date, -- 生日
insert_time timestamp --加入时间
);
* 复制表:
* create table 表名 like 被复制的表名;
create table mydb1 like mydb2; -- 把mydb2的数据复制到mydb1.
**2. R(Retrieve):查询**<br /> * 查询某个数据库中所有的表名称
* show tables; --显示数据库中所有表名称
* 查询表结构
* desc 表名; --显示表的的具体数据
**3. U(Update):修改**<br /> 1. 修改表名
alter table 表名 rename to 新的表名;
eg: alter table mydb1 rename to newdb; - 将mydb1重新命名为newdb.
- 修改表的字符集
```plsql
alter table 表名 character set 字符集名称;
alter table 表名 charset 字符集;
eg: alter table mydb1 character set utf8; -将mydb1的字符集设置为UTF-8
3. 添加一列
```plsql
alter table 表名 add 列名 数据类型;
eg: alter table mydb1 add teacher varchar(20); -给mydb1新增一列teacher
4. 修改列名称 类型
alter table 表名 change 列名 新列名 新数据类型;
eg: alter table mydb1 change score grade double; -将mydb1中score更改为grade 类型变为double
--- 只 修改列的类型
alter table 表名 modify 列名 新数据类型;
eg: alter table mydb1 modify score double;
- 删除列
4. D(Delete):删除 ```plsqlalter table 表名 drop 列名;
eg: alter table mydb1 drop score; --删除mydb1中的score列
- drop table 表名;
如果表存在,删除表eg: drop table mydb1; -删除表
insert into mydb1 values(1,’tom’,19,88,1996-1-1,);
* 注意:<br /> 1. 列名和值要一一对应。<br /> 2. 如果表名后,不定义列名,则默认给所有列添加值<br /> insert into 表名 values(值1,值2,...值n);<br /> 3. 除了数字类型,其他类型需要使用引号(单双都可以)引起来<br />**2. 删除数据:**<br /> 语法: ` delete from 表名 [where 条件]`<br />** * 注意:**<br /> 1. 如果不加条件,则删除表中所有记录。<br /> 2. 如果要删除所有记录<br /> 1.** `delete from 表名`**; -- 不推荐使用。有多少条记录就会执行多少次删除操作<br /> 1. **`TRUNCATE TABLE 表名`**; -- 推荐使用,效率更高 先删除表,然后再创建一张一样的表。
```plsql
delete from stu; -- 推荐使用
truncate table stu; --删除表 并创建一个相同的空表
3. 修改数据:
语法: update 表名 set 列名1 = 值1, 列名2 = 值2,... [where 条件];
update stu set name="zhangsan", age=20, grade=75.5; -- 会将stu表中的所有的数据都更改为 “zhangsan 20 75.5”
update stu set name="zhangsan", age=20, grade=75.5 where id=10;--按照条件修个stu信息
* 注意:
1. 如果不加任何条件,则会将表中所有记录全部修改。
2.3.4DQL:查询表中的记录
1. 语法:
select
字段列表(需要显示的结果,用逗号隔开)
from
表名列表(一张表:单表查询 ; 多张表 :多表查询)
where
条件列表
group by
分组字段 (对结果进行分组)
having
分组之后的条件
order by
排序
limit
2. 基础查询
1. 多个字段的查询
select 字段名1,字段名2... from 表名 [where][group by][having][order by][limit];
* 注意:
如果查询所有字段,则可以使用来替代字段列表。但是尽量不要使用,查询的效率低。
2. 去除重复:
distinct
*3. 计算列
一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算)ifnull(表达式1,表达式2): -- null参与的运算,计算结果都为null
表达式1:哪个字段需要判断是否为null 如果该字段为null后的替换值。
4. 起别名:使用as关键字
as:as也可以省略 ```plsql select address from student; — 结果中会出现重复数据 select distinct address form student; — 使用distinct关键字消除重复 select distinct name,address from student; —当结果集中每行字段值不同时,则不会消除
select name,math,english,math+english from student; — 计算总成绩 发现若存在null值 则无法计算 需要将null值替换 — 使用ifnull(列名,替换值) select name,math,english,math+ifnull(english,0) from student; — 发现 结果集中列名比较长时 可以使用as关键字 改名 结果集列名 as 新列名 select name,math,english,math+ifnull(english,0) as 成绩 from student;
select name,math 数学,english 英语,math+ifnull(english,0) 成绩 from student;
<a name="vzSvW"></a>
#### 3. 条件查询
1. where子句后跟条件<br /> 2. 运算符
```plsql
(1) > 、< 、<= 、>= 、= 、<>
(2) BETWEEN...AND
(3) IN( 集合)
(4) LIKE:模糊查询
占位符: _:单个任意字符
%:多个任意字符
(5) IS NULL
(6) and 或 && or 或 || not 或 !
4.模糊查询
LIKE 操作符**用于在 WHERE 子句中搜索列中的指定模式。
可以和通配符(%、_)配合使用,其中“%”表示0或多个任意的字符。“_”表示一个任意的字符。*
语法:`SELECT 列 | FROM 表名 WHERE 列名 LIKE 值`
-- 查询姓马的有哪些? 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 '%德%';
5.多行函数查询
多行函数也叫做聚合(聚集)函数,根据某一列或所有列进行统计。
(将一列数据作为一个整体,进行纵向的计算)
常见的多行函数有:
多行函数 | 作用 |
---|---|
COUNT( 列名 (主键)| * ) | 统计结果集中某一列或记录行的行数。 |
MAX( 列名 ) | 统计结果集中某一列值中的最大值 |
MIN( 列名 ) | 统计结果集中某一列值中的最小值 |
SUM( 列名 ) | 统计结果集中某一列所有值的和 |
AVG( 列名 ) | 统计结果集中某一列值的平均值 |
提示:
(1)多行函数不能用在where子句中
(2)多行函数和是否分组有关,分组与否会直接影响多行函数执行的结果。
(3)聚合函数里面的计算,排除bull值。
解决方案:(1)使用不为null的列
(2)使用ifnull()
(4) 在count()中,**表示:只要这一行数据有一个不为null,那就算一条记录。
* 一般不推荐使用。这里可以使用主键(不为空)。
(这里采用员工表的实例)
-- .统计emp表中薪资大于3000的员工个数
select count(*) from emp where sal>3000; select count(id) from emp where sal>3000;
-- .求emp表中的最高薪资
select sal from emp;
--求所有薪资
select max(sal) from emp;
--求最高薪资
select min(sal) from emp;
--求最低薪资
select name,max(sal) from emp; --错误写法 name不对应
解决方案:
select name,sal from emp order by sal desc limit 0,1;
-- .统计emp表中所有员工的薪资总和(不包含奖金)
select sal from emp;--统计薪资的所有值
select sum(sal) from emp; -- 统计所有薪资的总和
select sun(bonus) from emp; -- 统计所有的奖金总和
select sum( ifnull(bonus,0) )from emp; -- 奖金总和
-- .统计emp表员工的平均薪资(不包含奖金)
select avg(sal) from emp; -- 平均薪资
select avg(ifnull(bonus,0)) from emp; -- 平均奖金
多行函数需要注意的问题:
1)多行函数和是否分组有关,如果查询结果中的数据没有经过分组,默认整个查询结果是一个组,多行函数就会默认统计当前这一个组的数据。产生的结果只有一个。
2)如果查询结果中的数据经过分组(分的组不止一个),多行函数会根据分的组进行统计,有多少个组,就会统计出多少个结果。
-- 统计员工表的总人数
select count(*) from emp; 返回的就是emp表中的所有人数
再例如: 根据性别进行分组,再统计emp表中每组的人数,显示性别和对应人数
select gender,count(*) from emp group by gender;
select * from emp group by dept; -- 按照部门进行分组
6.分组查询
GROUP BY 语句
根据一个或多个列对结果集进行分组。
在分组的列上我们可以使用 COUNT,SUM,AVG,MAX,MIN等函数。
语法:**SELECT 列 | FROM 表名 [WHERE子句] GROUP BY 列名;
注意:
1.分组之后查询的字段:聚合函数、分组字段 显示其他字段没有意义。
2. where 和 having 的区别?
1. where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来
2. where 后不可以跟聚合函数,having可以进行聚合函数的判断。*/
-- 32.对emp表按照部门对员工进行分组,查看分组后效果。
select * from emp group by dept;-- 按照部门进行分组
-- 33.对emp表按照职位进行分组,并统计每个职位的人数,显示职位和对应人数
select job,count(*) from emp group by job;
-- 34.对emp表按照部门进行分组,求每个部门的最高薪资(不包含奖金),显示部门名称和最高薪资
select dept,max(sal) from emp group by dept;
--满足上一个条件的同时部门人数大于5
select dept,max(sal) from emp group by dept having count(id)>5;
7.排序查询
使用 ORDER BY 子句 将结果集中记录根据指定的列排序后再返回
语法:**SELECT 列名 FROM 表名** ORDER BY 列名 [ASC|DESC]
ASC(默认)升序,即从低到高;DESC 降序,即从高到低。
对emp表中所有员工的薪资进行升序(从低到高)排序,显示员工姓名、薪资。
select name,sal from emp order by sal asc(升序为默认 可以不写asc)
select name,sal from emp order by sal;
对emp表中所有员工的奖金进行降序(从高到低)排序,显示员工姓名、奖金。
select name,bonus from emp order by bonus desc;
select name,bonus from emp order by bonus desc,sal asc; 这里sal为第二排序条件 当bonus一样时才会按sal排序
指出第二排序条件: 当排序完有相同数据的时候,可以增加排序条件,来进行二次排序。
8.分页查询
在mysql中,通过limit进行分页查询:
limit (页码-1)*每页显示记录数, 每页显示记录数
查询emp表中的所有记录,分页显示:每页显示3条记录
select * from emp limit 0,3; --返回第一页 每页三条
select * from emp limit 3,3; --返回第二页 每页三条
select * from emp limit 6,3; --返回第三页 每页三条
select * from emp limit 9,3; --返回第四页 每页三条
9.日期时间函数查询
函数名 | 解释说明 |
---|---|
curdate() | 获取当前日期,格式是:年月日 |
curtime() | 获取当前时间 ,格式是:时分秒 |
sysdate()/now() | 获取当前日期+时间,格式是:年月日 时分秒 |
year(date) | 返回date中的年份 |
month(date) | 返回date中的月份 |
day(date) | 返回date中的天数 |
hour(date) | 返回date中的小时 |
minute(date) | 返回date中的分钟 |
second(date) | 返回date中的秒 |
CONCAT(s1,s2..) | 将s1,s2 等多个字符串合并为一个字符串 |
CONCAT_WS(x,s1,s2..) | 同CONCAT(s1,s2,..)函数,但是每个字符串之间要加上x,x是分隔符 |
-- 查询emp表中所有在1993和1995年之间出生的员工,显示姓名、出生日期。
select name,birthday from emp where birthday between 1993 and 1995; -- 错误写法 date类型的数据无法与年份比较
正确写法:
select name,birthday from emp where year(birthday) between 1993 and 1995;
或者
select name,birthday from emp where birthday between '1993-1-1' and '1995-12-31';
-- 查询emp表中本月过生日的所有员工
select * from emp where month( birthday ) = month( curdate() )
-- 查询emp表中员工的姓名和薪资(薪资格式为 :xxx(元))
select name concat(sal,'(元)') from emp;
补充l练习
select name,concat(sal,'/元') from emp; select name,concat_ws('/',sal,'元') from emp;
-- 按照性别分组。分别查询男、女同学的平均分
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 COUNT(id) > 2;
-- 使用聚合函数较长时 我们可以起个别名
SELECT sex , AVG(math),COUNT(id) 人数 FROM student WHERE math > 70 GROUP BY sex HAVING 人数 > 2;
SQL语句的书写顺序:
select * | 列名 -- 确定要查询的列有哪些
from 表名 -- 确定查询哪张表
where 条件 -- 通过筛选过滤,剔除不符合条件的记录
group by 分组的列 -- 指定根据哪一列进行分组
having 条件 -- 通过条件对分组后的数据进行筛选过滤
order by 排序的列 -- 指定根据哪一列进行排序
limit (countPage-1)*rowCount, rowCount -- 指定返回第几页记录以及每页显示多少条
SQL语句的执行顺序:
from 表名 -- 确定查询哪张表
where 条件 -- 通过筛选过滤,剔除不符合条件的记录
select * | 列名 列别名 -- 确定要查询的列有哪些,
group by 分组的列 -- 指定根据哪一列进行分组
having 条件 -- 通过条件对分组后的数据进行筛选过滤
order by 排序的列 -- 指定根据哪一列进行排序
limit (countPage-1)*rowCount, rowCount
2.4 字段约束
概念: 对表中的数据进行限定,保证数据的正确性、有效性和完整性。
分类:
1. **主键约束:primary key**
2.** 非空约束:not null**
3. **唯一约束:unique**
4. **外键约束:foreign key**
2.4.1主键约束
主键约束:**primary key**。
注意:
1. 含义:非空且唯一
2. 一张表只能有一个字段为主键
3. 主键就是表中记录的唯一标识
主键的作用: 作为一个唯一标识,唯一的表示一条表记录(作用类似于人的身份证号,可以唯一的表示一个人一样。)
1. 在创建表时,添加主键约束
create table stu(
id int primary key,-- 给id添加主键约束
name varchar(20)
);
2. 删除主键
-- 错误 alter table stu modify id int ;
ALTER TABLE stu DROP PRIMARY KEY;
3. 创建完表后,添加主键
ALTER TABLE stu MODIFY id INT PRIMARY KEY;
* 主键自增
如果主键是数值类型,为了方便插入主键(并且保证插入数据时,主键不会因为重复而报错),可以设置一个主键自增策略。
主键自增策略是指:设置了自增策略的主键,可以在插入记录时,不给id赋值,只需要设置一个null值,数据库会自动为id分配一个值(AUTO_INCREMENT变量,默认从1开始,后面依次+1),这样既可以保证id是唯一的,也省去了设置id的麻烦。
1.在创建表时,添加主键约束,并且完成主键自增长
create table stu(
id int primary key auto_increment,-- 给id添加主键约束
name varchar(20)
);
2.创建好之后添加:
alter table stu modify id int primary key auto_increment;
3.删除:
alter table stu modify id int;
2.4.2非空约束
非空约束:如果为一个列添加了非空约束,那么这个列的值就不能为空,但可以重复。
添加非空约束,例如为password添加非空约束:(not null,值不能为null)
1. 创建表时添加约束
CREATE TABLE stu(
id INT,
NAME VARCHAR(20) NOT NULL -- name为非空
);
2. 创建表完后,添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
3. 删除name的非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);
2.4.3唯一约束
唯一约束:如果为一个列添加了唯一约束,那么这个列的值就必须是唯一的(即不能重复),但可以为空。
唯一约束:unique,值不能重复
1. 创建表时,添加唯一约束
CREATE TABLE stu(
id INT,
phone_number VARCHAR(20) UNIQUE -- 添加了唯一约束);
* 注意mysql中,唯一约束限定的列的值可以有多个null
2. 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
3.在创建表后,添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
2.4.4外键约束
外键其实就是用于通知数据库两张表数据之间对应关系的这样一个列。
这样数据库就会帮我们维护两张表中数据之间的关系。
如果将dept_id列设置为外键,等同于通知数据库,部门表和员工表之间存在对应关系,dept_id列中的数据要参考部门的主键,数据库一旦知道部门和员工表之间存在关系,就会帮我们维护这层关系型。语法:
create table 表名(
....
外键列
[constraint 外键名称] foreign key (外键列名称) references 主表名称(主表列名称)
);
1. 在创建表时,可以添加外键
create table emp(
id int,
name varchar(50),
dept_id int,
foreign key(dept_id) references dept(id)
);
2. 删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
3. 创建表之后,添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称)
REFERENCES 主表名称(主表列名称);
2.4.5级联操作
1. 添加级联操作
语法:ALTER TABLE 表名 ADD CONSTRAINT 外键名称
**FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称)**
**ON UPDATE CASCADE**
**ON DELETE CASCADE ;**
2. 分类:
1. 级联更新:ON UPDATE CASCADE
2. 级联删除:ON DELETE CASCADE
3.数据库表设计
3.1 表关系
3.2数据库设计的范式
1.概念:
设计数据库时,需要遵循的一些规范。要遵循后边的范式要求,必须先遵循前边的所有范式要求。
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
2.分类
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
3.详解
1. 第一范式(1NF):
每一列都是不可分割的原子数据项。
这张表的字段列中系里面包含两个子列,违反了第一范式。需要将其拆分为单独的列。
第一范式的问题:
1.存在严重的数据冗余:学号,姓名,系
2.数据添加时存在问题:添加新的系别和系主任 数据不合法
3.删除数据存在问题:删除某个同学的列会将整个系删除。
2. 第二范式(2NF):
在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)。
几个概念:
- 函数依赖:A—>B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A
例如:学号—>姓名。 (学号,课程名称) —> 分数 - 完全函数依赖:A—>B, 如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。
例如:(学号,课程名称) —> 分数 - 部分函数依赖:A—>B, 如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。
例如:(学号,课程名称) — > 姓名 - 传递函数依赖:A—>B, B — >C . 如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称 C 传递函数依赖于A
例如:学号—>系名,系名—>系主任 - 码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码
例如:该表中码为:(学号,课程名称)
- 主属性:码属性组中的所有属性
- 非主属性:除过码属性组的属性
4.数据库备份与恢复
4.1 备份数据库
在cmd窗口中(未登录的状态下),可以通过如下命令对指定的数据库进行备份:
示例1: 对db40库中的数据(表,表记录)进行备份,备份到 d:/db40.sql文件中
也可以一次性备份所有库,例如:
键入密码,如果没有提示错误(警告信息不是错误,可以忽略),即表示备份成功!
4.2 恢复数据库
1、恢复数据库方式一:
在cmd窗口中(未登录的状态下),可以通过如下命令对指定的数据库进行恢复:
示例:将d:/db40.sql文件中的数据恢复到db60库中
2、恢复数据库方式二:
在cmd窗口中(已登录的状态下),可以通过source执行指定位置的SQL文件:
示例:将d:/db40.sql文件中的数据恢复到db80库中