MySQL - Note01 Table

DB, DBMS, SQL

  • DB(DataBase): 数据库(在硬盘上以文件形式存在)
  • DBMS(DataBase Management System): 数据库管理系统(MySQL, Oracle, SQL Server, DB2, Sybase…)
  • SQL(Sequel): 结构化查询语言,是一门标准通用的语言,适合所有的数据库产品

DBMS -(执行)-> SQL -(操作)-> DB

Table

table是数据库的基本组成单元,所有的数据都以表格的形式组织,可读性非常强。

  • 一个表包括行和列

    行:被称为数据/记录(data)

    列:被称为字段(column)

    学号(int) 姓名(archar) 年龄(int)
    101 张三 20
    102 李四 21

    每个字段应该包括:字段名、数据类型、相关约束

  • 导入的learning表结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    mysql> show tables;
    /*
    +--------------------+
    | Tables_in_learning |
    +--------------------+
    | dept | 部门表
    | emp | 员工表
    | salgrade | 工资等级表
    +--------------------+
    3 rows in set (0.00 sec)
    */
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    mysql> desc dept;
    /*
    +--------+-------------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +--------+-------------+------+-----+---------+-------+
    | DEPTNO | int(2) | NO | PRI | NULL | | 部门编号
    | DNAME | varchar(14) | YES | | NULL | | 部门名称
    | LOC | varchar(13) | YES | | NULL | | 部门位置
    +--------+-------------+------+-----+---------+-------+
    3 rows in set (0.01 sec)
    */
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    mysql> desc emp;
    /*
    +----------+-------------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +----------+-------------+------+-----+---------+-------+
    | EMPNO | int(4) | NO | PRI | NULL | | 员工编号
    | ENAME | varchar(10) | YES | | NULL | | 员工姓名
    | JOB | varchar(9) | YES | | NULL | | 员工岗位
    | MGR | int(4) | YES | | NULL | | 上级领导编号
    | HIREDATE | date | YES | | NULL | | 入职日期
    | SAL | double(7,2) | YES | | NULL | | 薪资
    | COMM | double(7,2) | YES | | NULL | | 补助/津贴
    | DEPTNO | int(2) | YES | | NULL | | 部门编号
    +----------+-------------+------+-----+---------+-------+
    8 rows in set (0.00 sec)
    */
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    mysql> desc salgrade;
    /*
    +-------+---------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +-------+---------+------+-----+---------+-------+
    | GRADE | int(11) | YES | | NULL | | 等级
    | LOSAL | int(11) | YES | | NULL | | 最低薪资
    | HISAL | int(11) | YES | | NULL | | 最高薪资
    +-------+---------+------+-----+---------+-------+
    3 rows in set (0.00 sec)
    */

创建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 建表语法格式
# 表名一般用t_或tbl_开头用以区分
create table [table_name](
[字段1] [数据类型] [约束],
[字段2] [数据类型] [约束],
[字段3] [数据类型] [约束],
...
);

/*
eg.创建学生表:
学号(bigint)、姓名(varchar)、性别(char)、班级编号(int)、生日(char)
*/
create table t_student(
no bigint(11),
name varchar(255),
sex char(1),
classno int(4),
birth char(10)
);

MySQL中常见的数据类型:

Date Struct Java Description
int(整数型) int
bigint(长整型) long
float(浮点型) float, double
char(定长字符串) String 性别、生日
varchar(可变长字符串) StringBuffer, StringBuilder 姓名、简介
date(日期类型) java.sql.Date
BLOB(二进制大对象) Object Binary Large Object(存储图片、视频等流媒体信息)
CLOB(字符大对象) Object Character Large Object(存储较大的文本,如4G的字符串)

约束(Constraint)

在创建表的时候,可以给表的字段添加相应的约束。添加约束的目的是为了保证表中数据的合法性、有效性、完整性。

常见的约束

约束名 约束作用
非空约束(not null) 约束的字段不能为NULL
唯一约束(unique) 约束的字段不能重复
主键约束(primary key) 简称PK,约束的字段既不能为NULL,也不能重复
外键约束(foreign key) 简称FK…
default default [value]:添加默认数据

检查约束(check):仅Oracle数据库有,MySQL暂不支持

非空约束(not null)

1
2
3
4
5
6
7
8
9
10
create table t_user(
id int,
username varchar(255) not null,
password varchar(255)
);

insert into t_user(id, password) value(101, '123');
/*
ERROR 1364 (HY000): Field 'username' doesn't have a default value
*/

唯一性约束(unique)

唯一性约束修饰的字段具有唯一性,不能重复,但可以为NULL

1
2
3
4
5
6
7
8
9
10
11
# eg.给某一列添加 unique(列级约束)
drop table if exists t_user;

create table t_user(
id int unique,
username varchar(255)
);

insert into t_user values(101, 'vv'), (101, 'yy');

# ERROR 1062 (23000): Duplicate entry '101' for key 'id'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# eg.给两个列或者多个列添加 unique (表级约束)
/*
使用:unique([name1], [name2])
联合检测 [name1][name2]
*/
drop table if exists t_user;

create table t_user(
id int,
user_id int,
user_name char(2),
unique(user_id, user_name)
);

insert into t_user
values(101, 001, 'vv'),
(101, 002, 'yy'),
(102, 001, 'zz');

/*
+------+---------+-----------+
| id | user_id | user_name |
+------+---------+-----------+
| 101 | 1 | vv |
| 101 | 2 | yy |
| 102 | 1 | zz |
+------+---------+-----------+
3 rows in set (0.00 sec)
*/

主键约束

主键中的字段不能为空,也不能重复

如何给一张表添加主键约束?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
drop table if exists t_user;

create table t_user(
id int primary key,
username varchar(2),
email varchar(255)
);

insert into t_user
values(101, 'vv', 'vv@123.com'),
(102, 'yy', 'yy@456.com'),
(103, 'zz', 'zz@789.com');

insert into t_user(id, username, email) values(101, 'xx', 'xx@101.com');
# ERROR 1062 (23000): Duplicate entry '101' for key 'PRIMARY'

insert into t_user(username, email) values('xx', 'xx@101.com');
# ERROR 1364 (HY000): Field 'id' doesn't have a default value

表级约束:primary key([字段1], [字段2])

相关术语

主键约束:primary key

主键字段:添加了主键约束的字段

主键值:id字段中的每个值

主键作用

主键值是这行记录在这样表中的唯一标识,一张表的主键约束只能有一个

表的设计三范式中,第一范式就要求任何一张表都应有主键

主键分类
  • 根据主键字段的字段数量来划分:

    单一主键:推荐、常用

    复合主键:使用表级约束多个字段联合起来添加一个主键约束(不建议,违背三范式)

  • 根据主键性质来划分:

    自然主键:和业务没有任何关系的自然数

    业务主键:主键和系统的业务挂钩(不建议)

    最好不要用业务挂钩的字段作为主键,业务改变后,主键无法更改时则冲突

    例如:银行卡卡号、身份证号

*MySQL 提供主键值自增

在约束后添加 auto_increment

1
2
3
4
5
6
7
8
9
10
11
drop table if exists t_user;

create table t_user(
id int primary key auto_increment,
user_name varchar(2)
);

insert into t_user(user_name)
values('vv'), ('yy'), ('zz'), ('xx');

select * from t_user;

外键约束

外键约束的字段必须来自于指定表中的某一字段值

外键可以为 NULL

不一定引用主键,起码得有唯一性(unique)

相关术语

外键约束:foreign key([name]) references [table]([name])

外键字段:添加有外键约束的字段

外键值:外键字段中的每一个值

父子表

设计数据库表,用来维护学生和班级信息

方案1:一张表存储所有数据(不推荐,冗余)

1
2
3
4
5
6
---------------------------------------------
sno(pk) sname classno classname
---------------------------------------------
1 vv 1804 软工4班
2 yy 1806 软工6班
3 zz 1703 软工3班

方案2:两张表(班级表和学生表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
t_class 班级表(父表)
----------------------
classno(pk) cname
----------------------
1804 软工4班
1806 软工6班
1703 软工3班

t_student 学生表(子表)
--------------------------------
sno sname classno(fk)
--------------------------------
1 vv 1804
2 yy 1806
3 zz 1703
  • t_student 中的 calssno 引用 t_class 中的 classno 字段,此时 t_student 叫做子表,t_class 叫做父表
  • 顺序要求:
    • 创建时先父再子
    • 删除时先子再父

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
drop table if exists t_student;
drop table if exists t_class;

create table t_class(
classno int,
classname varchar(255),
primary key(classno)
);

create table t_student(
sno int,
sname varchar(255),
classno int,
primary key(sno),
foreign key(classno) references t_class(classno)
);

insert into t_class
values(1804, 'PG4'),
(1806, 'PG6'),
(1703, 'PG3');

insert into t_student
values(1, 'vv', 1804),
(2, 'yy', 1806),
(3, 'zz', 1703);

select * from t_class;
select * from t_student;

/*
+---------+-----------+
| classno | classname |
+---------+-----------+
| 1703 | PG3 |
| 1804 | PG4 |
| 1806 | PG6 |
+---------+-----------+
3 rows in set (0.00 sec)

+-----+-------+---------+
| sno | sname | classno |
+-----+-------+---------+
| 1 | vv | 1804 |
| 2 | yy | 1806 |
| 3 | zz | 1703 |
+-----+-------+---------+
3 rows in set (0.00 sec)
*/

# 子表尝试插入不存在的 fk
insert into t_student values(4, 'zz', 1901);
/*
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`learning`.`t_student`, CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`classno`) REFERENCES `t_class` (`classno`))
*/

insert语句插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 语法格式
insert into [table_name](字段1,字段2,字段3,...) values(值1,值2,值3,...)

# eg1.插入数据
insert into t_student(no, name, sex, classno, birth)
values(20184225131, 'vv', '1', 1804, '2000-12-26');

# eg2.插入数据
# 省略字段,则values全填写
insert into t_student
values(20184225132, 'yy', '0', 1804, '2000-4-7');

# eg3.插入数据
# 一次插入多行数据
insert into t_student
values(20184225133, 'xx', '1', 1804, '2011-12-5'),
(20184225134, 'zz', '0', 1804, '2001-4-16');

/*
+-------------+------+------+---------+------------+
| no | name | sex | classno | birth |
+-------------+------+------+---------+------------+
| 20184225131 | vv | 1 | 1804 | 2000-12-26 |
| 20184225132 | yy | 0 | 1804 | 2000-4-7 |
| 20184225133 | xx | 1 | 1804 | 2011-12-5 |
| 20184225134 | zz | 0 | 1804 | 2001-4-16 |
+-------------+------+------+---------+------------+
4 rows in set (0.00 sec)
*/

/*
字段的数量和值的数量相同
数据类型要对应相同
顺序无关
空字段自动插入NULL
insert只能增,执行成功后表格必然多一行记录
*/

删除表

通用语法: drop table [table_name]

MySQL语法: drop table if exists [table_name];

if exists:如果存在

复制表

将查询结果当作表创建出来

1
2
3
4
5
6
7
# 语法格式
create table [table_name]
as [DQL语句];

# eg
create table emp1
as select * from emp;

插入表

将查询结果当作表插入到别的表

1
2
3
4
5
# 语法格式
insert into [table_name] [DQL语句];

# eg
insert into emp1 select * from dept;

修改表数据

语法格式

1
2
3
update [table_name]
set [字段1]=[值1], [字段2]=[值2], ...
where [条件];
  • 没有条件整张表数据全部更新
1
2
3
4
5
6
7
8
9
10
11
12
# 将部门10的LOC修改为SHANGHAI,将部门名称修改为RENSHIBU
update dept1 set dname='RENSHIBU', loc='SHANGHAI' where deptno='10';
/*
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | RENSHIBU | SHANGHAI |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
*/

删除表数据

语法格式:delete from [table_name] where [条件];

1
2
# eg.删除20部门数据
delete from dept1 where deptno='20';
  • 没有条件全部删除
1
2
# eg.删除所有数据
delete from dept1;

*如何删除大表中的数据?

可以使用 truncate 截断表数据,仅留下表头字段名,危险系数高,不可以回滚

delete 仅擦除数据,不释放空间,删除效率低下

语法格式:truncate table [table_name];


MySQL - Note01 Table
https://wataaaame.github.io/java/2022/04/17/MySQL - Note01 Table/
Author
Aaron Tang
Posted on
April 17, 2022
Licensed under