7856 字
39 分钟
05:mysql之表结构管理

[TOC]

05:mysql之表结构管理#

今日工作任务路线图

flowchart LR
subgraph BottomRow[表结构管理]
direction LR
A[表管理] --> B[表格字段数据类型] --> C[表头基本约束]
end
classDef highlight stroke:#f00,stroke-width:2px;
class E highlight;

一、工作场景#

小李在一家小型互联网公司担任数据库管理员。最近公司业务拓展,员工数量大幅增加,原本的数据库表结构逐渐难以满足需求。

在员工表中,原先的“职位”字段过于笼统,无法精准区分不同岗位。部门表也没有记录各部门的成立时间,不利于做部门发展分析。薪资表中奖金计算方式单一,不能适应新的绩效制度。

小李意识到要对表结构进行优化。他先和各部门沟通,了解实际业务需求,再设计新的表结构,在员工表细化“职位”,部门表添加“成立时间”,薪资表调整奖金规则。最后在测试环境验证新结构,确保准确稳定后应用到正式环境。

二、为啥要学表结构管理#

学习 MySQL 表结构管理非常有必要。想象下你在一家公司工作,公司有员工表、部门表和薪资表。如果表结构管理不好,问题就会接踵而至。

要是员工表没有合理设置字段,可能会导致员工信息记录不全,影响人事管理。部门表结构混乱,就很难清晰掌握各部门的情况。薪资表如果设计不佳,计算薪资时容易出错,引发员工不满。

学会表结构管理,能让这些表合理存储数据,查询和修改数据更高效,避免数据冗余和错误。可以准确统计各部门员工数量、快速算出员工薪资,让公司运营更顺畅,所以学好它对处理数据很有帮助。

三、表管理#

当前任务环节

flowchart LR
subgraph BottomRow[表结构管理]
direction LR
A[表管理] --> B[表格字段数据类型] --> C[表头基本约束]
end
classDef highlight stroke:#f00,stroke-width:2px;
class A highlight;

3.1 建库练习#

库名命名规则:

仅可以使用数字、字母、下划线、不能纯数字

区分字母大小写,

具有唯一性

不可使用MySQL命令或特殊字符

命令操作如下所示:

//库名区分字母大小写
mysql> create【克瑞特】 database【得塔-贝斯】 gamedb ;
-- mysql> create database gamedb;
Query OK, 1 row affected (0.14 sec)
mysql> create【克瑞特】 database【得塔-贝斯】 GAMEDB ;
-- mysql> create database GAMEDB;
Query OK, 1 row affected (0.08 sec)
mysql> create【克瑞特】 database【得塔-贝斯】 GAMEDB ;
-- mysql> create database GAMEDB;
ERROR 1007 (HY000): Can't create【克瑞特】 database【得塔-贝斯】 'GAMEDB'; database【得塔-贝斯】 exists【伊贼谁斯】' //重名报错
//加if not【nuō 特】 exists【伊贼谁斯】 命令避免重名报错
mysql> create【克瑞特】 database【得塔-贝斯】 if not【nuō 特】 exists【伊贼谁斯】 gamedb ;
-- mysql> create database if not exists gamedb;
Query OK, 1 row affected, 1 warning (0.03 sec) //正常
mysql> show【瘦】 databases【得塔-贝斯】; //查看创建的库
-- mysql> show databases;
+--------------------+
| Database |
+--------------------+
| GAMEDB |
| gamedb |
| information_schema |
| mysql |
| performance_schema |
| sys |
| moershi |
+--------------------+
7 rows in set (0.00 sec)
mysql> drop【卓-普】 database【得塔-贝斯】 gamedb; //删除库
-- mysql> drop database gamedb;
Query OK, 0 rows affected (0.11 sec)
mysql> drop【卓-普】 database【得塔-贝斯】 gamedb; // 删除没有的库报错
-- mysql> drop database gamedb;
ERROR 1008 (HY000): Can’t drop【卓-普】 database【得塔-贝斯】 ‘gamedb’; database【得塔-贝斯】 doesn’t exist
//加if exists【伊贼谁斯】 删除没有的库,也不报错
mysql> drop【卓-普】 database【得塔-贝斯】 if exists【伊贼谁斯】 gamedb;
-- mysql> drop database if exists gamedb;
Query OK, 0 rows affected, 1 warning (0.00 sec)

3.2 建表练习#

命令操作如下所示:

mysql> create【克瑞特】 database【得塔-贝斯】 studb【斯丢db】; //建库
-- mysql> create database studb;
Query OK, 1 row affected (0.11 sec)
mysql> create【克瑞特】 table【忒-部】 studb【斯丢db】.stu( //建表
-> name char【查尔】(10),
-> class【克拉斯】 char【查尔】(9),
-> gender【间德尔】 char【查尔】(4),
-> age int【因特】
-> );
-- mysql> create table studb.stu(
-- -> name char(10),
-- -> class char(9),
-- -> gender char(4),
-- -> age int);
Query OK, 0 rows affected (1.17 sec)
mysql> desc studb【斯丢db】.stu; //查看表头
-- mysql> desc studb.stu;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| name | char(10) | YES | | NULL | |
| class | char(9) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
| age | int | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)

3.3 修改表练习#

命令操作如下所示:

修改表名#

mysql> show【瘦】 tables【忒-部s】; //查看表
-- mysql> show tables;
+-----------------+
| Tables_in_studb |
+-----------------+
| stu |
+-----------------+
1 row in set (0.00 sec)
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stu rename【瑞-内姆】 studb【斯丢db】.stuinfo【斯丢因否】; //修改表名 rename【瑞-内姆】
-- mysql> alter table studb.stu rename studb.stuinfo;
Query OK, 0 rows affected (0.28 sec)
mysql> use studb【斯丢db】; //进入库
-- mysql> use studb;
Reading table【忒-部】 information for completion of table【忒-部】 and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show【瘦】 tables【忒-部s】; //查看表
-- mysql> show tables;
+-----------------+
| Tables_in_studb |
+-----------------+
| stuinfo |
+-----------------+
1 row in set (0.00 sec)

删除表头#

mysql> desc studb【斯丢db】.stu; //查看表头
-- mysql> desc studb.stu;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| name | char(10) | YES | | NULL | |
| class | char(9) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
| age | int | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stuinfo【斯丢因否】 drop【卓-普】 age ; //删除age表头 drop【卓-普】
-- mysql> alter table studb.stuinfo drop age;
Query OK, 0 rows affected (0.52 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc stuinfo【斯丢因否】; //查看表头
-- mysql> desc stuinfo;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| name | char(10) | YES | | NULL | |
| class | char(9) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

添加表头#

//添加表头,默认添加在末尾add
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stuinfo【斯丢因否】 add mail【miào e】 char【查尔】(30) ;
-- mysql> alter table studb.stuinfo add mail char(30);
Query OK, 0 rows affected (0.24 sec)
Records: 0 Duplicates: 0 Warnings: 0
//查看表头
mysql> desc studb【斯丢db】.stuinfo【斯丢因否】;
-- mysql> desc studb.stuinfo;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| name | char(10) | YES | | NULL | |
| class | char(9) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
| mail | char(30) | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)
//first【佛斯特】 把表头添加首位
//after【啊夫特】 添加在指定表头名的下方
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stuinfo【斯丢因否】 add number【能波】 char【查尔】(9) first【佛斯特】 , add school【斯故】 char【查尔】(10) after【啊夫特】 name;
-- mysql> alter table studb.stuinfo add number char(9) first,add school char(10) after name;
Query OK, 0 rows affected (0.48 sec)
Records: 0 Duplicates: 0 Warnings: 0
//查看表结构
mysql> desc studb【斯丢db】.stuinfo【斯丢因否】; //查看表头
-- mysql> desc studb.stuinfo;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| number | char(9) | YES | | NULL | |
| name | char(10) | YES | | NULL | |
| school | char(10) | YES | | NULL | |
| class | char(9) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
| mail | char(30) | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
6 rows in set (0.00 sec)

修改表头数据类型#

//修改表头数据类型modify【莫迪fái】
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stuinfo【斯丢因否】 modify【莫迪fái】 mail【miào e】 varchar【瓦儿-查儿】(50);
-- mysql> alter table studb.stuinfo modify mail varchar(50);
Query OK, 0 rows affected (1.17 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc studb【斯丢db】.stuinfo【斯丢因否】;
-- mysql> desc studb.stuinfo;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| number | char(9) | YES | | NULL | |
| name | char(10) | YES | | NULL | |
| school | char(10) | YES | | NULL | |
| class | char(9) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
| mail | varchar(50) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
6 rows in set (0.01 sec)

修改表头名#

//修改表头名class【克拉斯】
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stuinfo【斯丢因否】 change【趁(chèn)吉】 class【克拉斯】 班级 char【查尔】(9) ;
-- mysql> alter table studb.stuinfo change class 班级 char(9);
Query OK, 0 rows affected (0.12 sec)
Records: 0 Duplicates: 0 Warnings: 0
//查看表头
mysql> desc studb【斯丢db】.stuinfo【斯丢因否】;
-- mysql> desc studb.stuinfo;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| number | char(9) | YES | | NULL | |
| name | char(10) | YES | | NULL | |
| school | char(10) | YES | | NULL | |
| 班级 | char(9) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
| mail | varchar(50) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

删除多个表头#

//一起删除多个表头
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stuinfo【斯丢因否】 drop【卓-普】 school【斯故】 , drop【卓-普】 班级 ,drop【卓-普】 mail【miào e】 ;
-- mysql> alter table studb.stuinfo drop school,drop 班级,drop mail;
Query OK, 0 rows affected (0.73 sec)
Records: 0 Duplicates: 0 Warnings: 0
//查看表头
mysql> desc studb【斯丢db】.stuinfo【斯丢因否】;
-- mysql> desc studb.stuinfo;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| number | char(9) | YES | | NULL | |
| name | char(10) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

修改表头的位置#

mysql>
//使用modify【莫迪fái】 修改表头的位置
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stuinfo【斯丢因否】 modify【莫迪fái】 gender【间德尔】 char【查尔】(4) after【啊夫特】 number【能波】;
-- mysql> alter table studb.stuinfo modify gender char(4) after number;
Query OK, 0 rows affected (0.77 sec)
Records: 0 Duplicates: 0 Warnings: 0
//查看表头
mysql> desc studb【斯丢db】.stuinfo【斯丢因否】;
-- mysql> desc studb.stuinfo;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| number | char(9) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
| name | char(10) | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)
//再修改回原来位置
mysql> alter【奥-特】 table【忒-部】 studb【斯丢db】.stuinfo【斯丢因否】 modify【莫迪fái】 gender【间德尔】 char【查尔】(4) after【啊夫特】 name;
-- mysql> alter table studb.stuinfo modify gender char(4) after name;
Query OK, 0 rows affected (0.50 sec)
Records: 0 Duplicates: 0 Warnings: 0
//查看表头
mysql> desc studb【斯丢db】.stuinfo【斯丢因否】;
-- mysql> desc studb.stuinfo;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| number | char(9) | YES | | NULL | |
| name | char(10) | YES | | NULL | |
| gender | char(4) | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
3 rows in set (0.01 sec)

3.4 复制表#

拷贝已有的表 和系统命令 cp 的功能一样

复制表#

-- create table 表名 select * from 表名
//复制moershi库salary【晒了瑞】表到 studb【斯丢db】库 表名不变
mysql> create【克瑞特】 table【忒-部】 studb【斯丢db】.salary【晒了瑞】 select【涩莱克特】 * from【弗乱】 moershi.salary【晒了瑞】;
-- mysql> create table studb.salary select * from moershi.salary;
Query OK, 8055 rows affected (2.66 sec)
Records: 8055 Duplicates: 0 Warnings: 0
//查看表头,源表的key【kì】 不会被复制
mysql> desc studb【斯丢db】.salary【晒了瑞】;
-- mysql> desc studb.salary;
+-------------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------+------+-----+---------+-------+
| id | int | NO | | 0 | |
| date | date | YES | | NULL | |
| employee_id | int | YES | | NULL | |
| basic | int | YES | | NULL | |
| bonus | int | YES | | NULL | |
+-------------+------+------+-----+---------+-------+
5 rows in set (0.00 sec)
//查看表行数
mysql> select【涩莱克特】 count【kàn特】(*) from【弗乱】 studb【斯丢db】.salary【晒了瑞】;
-- mysql> select count(*) from studb.salary;
+----------+
| count(*) |
+----------+
| 8055 |
+----------+
1 row in set (0.00 sec)

复制表头#

//仅仅复制表头like【赖特
mysql> create【克瑞特】 table【忒-部】 studb【斯丢db】.salary2【晒了瑞2】 like【赖特】 moershi.salary【晒了瑞】;
-- mysql> create table studb.salary2 like moershi.salary;
Query OK, 0 rows affected (0.95 sec)
//查看表头
mysql> desc studb【斯丢db】.salary2【晒了瑞2】;
-- mysql> desc studb.salary2;
+-------------+------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| date | date | YES | | NULL | |
| employee_id | int | YES | MUL | NULL | |
| basic | int | YES | | NULL | |
| bonus | int | YES | | NULL | |
+-------------+------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
//查看表行数
mysql> select【涩莱克特】 count【kàn特】(*) from【弗乱】 studb【斯丢db】.salary2【晒了瑞2】;
-- mysql> select count(*) from studb.salary2;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)
mysql>

四、表的字段数据类型#

数值类型:INT存储整数,DECIMAL存储精确小数 字符类型:CHAR适合固定长度,VARCHAR适合可变长度 日期时间:DATE存储日期,TIME存储时间 枚举类型:ENUM存储预定义值列表

当前任务环节

flowchart LR
subgraph BottomRow[表结构管理]
direction LR
A[表管理] --> B[表格字段数据类型] --> C[表头基本约束]
end
classDef highlight stroke:#f00,stroke-width:2px;
class B highlight;

常用数据类型:数值类型、字符类型、日期时间类型、枚举类型,每种类型都有对应的命令表示、有具体的存储范围。

  • 比如存储: 身高、体重、工资、奖金,适合使用数值类型。
  • 比如存储: 姓名、家庭地址、收货地址,适合使用字符类型。char
  • 比如存储: 生日、出生年份、入职时间、下班时间、注册时间,适合使用日期时间。date(日期) time(时间) datetime(时间日期) yeaer(年份)
  • 比如存储: 爱好、性别、社保医院,适合使用枚举类型。

4.1 练习字符类型的使用#

命令操作如下所示:

//建表
mysql> create【克瑞特】 table【忒-部】 studb【斯丢db】.t2(name char【查尔】(3) , address【额拽斯】 varchar【瓦儿-查儿】(5) );
-- mysql> create table studb.t2(name char(3),adderss varchar(5));
Query OK, 0 rows affected (0.30 sec)
//查看表头
mysql> desc studb【斯丢db】.t2;
-- mysql> desc studb.t2;
+---------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| name | char(3) | YES | | NULL | |
| address | varchar(5) | YES | | NULL | |
+---------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
//插入记录
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t2 values【挖柳斯】 ("a","a"); //正常
-- mysql> insert into studb.t2 values("a","a");
Query OK, 1 row affected (0.05 sec)
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t2 values【挖柳斯】 ("ab","ab"); //正常
-- mysql> insert into studb.t2 values ("ab","ab");
Query OK, 1 row affected (0.08 sec)
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t2 values【挖柳斯】 ("abc","abc");//正常
-- mysql> insert into studb.t2 values ("abc","abc");
Query OK, 1 row affected (0.04 sec)
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t2 values【挖柳斯】 ("abcd","abcd"); //超出字符个数报错
-- mysql> insert into studb.t2 values ("abcd","abcd");
ERROR 1406 (22001): Data too long for column 'name' at row 1

mysql8 建表默认支持中文字符集

//查看字符集
mysql> show【瘦】 create【克瑞特】 table【忒-部】 studb【斯丢db】.t2 \G
-- mysql> show create table studb.t2 \G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`name` char【查尔】(3) DEFAULT NULL【nào】,
`address【额拽斯】` varchar【瓦儿-查儿】(5) DEFAULT NULL【nào】
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
说明 :
ENGINE=InnoDB 定义存储引擎(存储引擎课程里讲)
DEFAULT CHARSET=定义表使用的字符集
//插入记录
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t2 values【挖柳斯】 ("张翠山","武当山");
-- mysql> insert into studb.t2 values("张翠山","武当山");
Query OK, 1 row affected (0.07 sec)
//查看表记录
mysql> SELECT【涩莱克特】 * FROM【弗乱】 studb【斯丢db】.t2;
-- mysql> select * from studb.t2;
+-----------+-----------+
| name | address |
+-----------+-----------+
| a | a |
| ab | ab |
| abc | abc |
| 张翠山 | 武当山 |
+-----------+-----------+
4 rows in set (0.00 sec)

4.2 练习数值类型的使用#

命令操作如下所示:

//建表
mysql> create【克瑞特】 table【忒-部】 studb【斯丢db】.t1(name char【查尔】(10) , level【列沃】 tinyint【泰尼因特】 unsigned【安赛因德】 , money【孟妮】 double【答步】 );
-- mysql> create table studb.t1(name char(10),level tinyint unsigned , money double );
Query OK, 0 rows affected (0.72 sec)
//查看表头
mysql> desc studb【斯丢db】.t1;
-- mysql> desc studb.t1;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| name | char(10) | YES | | NULL | |
| level | tinyint unsigned | YES | | NULL | |
| money | double | YES | | NULL | |
+-------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
//插入数据
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t1 values【挖柳斯】("法师",80,88);
-- mysql> insert into studb.t1 values("法师",80,88);
Query OK, 1 row affected (0.04 sec)
//超出范围报错 tinyint unsigned 最大255 可以是小数,四舍五入取整
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t1 values【挖柳斯】("战士",301,1.292);
-- mysql> insert into studb.t1 values("战士",301,1.292);
ERROR 1264 (22003): Out of range value for column 'level【列沃】' at row 1 -- 失败是因为值301超出了TINYINT UNSIGNED的数据范围(0-255)
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t1 values【挖柳斯】("猎人",255,1.292);
-- mysql> insert into studb.t1 values("猎人",255,1.292);
Query OK, 1 row affected (0.06 sec)
//整数类型 不存储小数位
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t1 values【挖柳斯】 ("英雄",1.292,6.78);
-- mysql> insert into studb.t1 values("英雄",1.292,6.78);
Query OK, 1 row affected (0.07 sec)
//查看表记录
mysql> select【涩莱克特】 * from【弗乱】 studb【斯丢db】.t1 ;
-- mysql> select * from studb.t1;
+--------+-------+-------+
| name | level | money |
+--------+-------+-------+
| 法师 | 80 | 88 |
| 猎人 | 255 | 1.292 |
| 英雄 | 1 | 6.78 |
+--------+-------+-------+
3 rows in set (0.00 sec)

4.3 枚举类型#

//建表
mysql> create【克瑞特】 table【忒-部】 studb【斯丢db】.t8(
-> 姓名 char【查尔】(10),
-> 性别 enum【伊牛姆】("男","女","保密"),
-> 爱好 set【赛特】("帅哥","金钱","吃","睡")
-> );
-- mysql> create table studb.t8(
-- -> 姓名 char(10),
-- -> 性别 enum("男","女","保密"),
-- -> 爱好 set("帅哥","金钱","吃","睡"));
Query OK, 0 rows affected (0.29 sec)
//查看表头
mysql> desc studb【斯丢db】.t8 ;
-- mysql> desc studb.t8;
+--------+------------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------------------------+------+-----+---------+-------+
| 姓名 | char(10) | YES | | NULL | |
| 性别 | enum('男','女','保密') | YES | | NULL | |
| 爱好 | set('帅哥','金钱','吃','睡') | YES | | NULL | |
+--------+------------------------------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
//插入记录超出范围报错
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t8 values【挖柳斯】 ("小包总","男人","帅哥,睡,金钱");
-- mysql> insert into studb.t8 values ("小包总","男人","帅哥,睡,金钱");
ERROR 1265 (01000): Data truncated for column '性别' at row 1 -- 值"男人"不在ENUM类型的预定义值列表中(只有'男','女','保密')
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t8 values【挖柳斯】 ("小包总","男","美女,睡,金钱");
-- mysql> insert into studb.t8 values ("小包总","男","美女,睡,金钱");
ERROR 1265 (01000): Data truncated for column '爱好' at row 1 --"爱好"字段只包含'帅哥','金钱','吃','睡'四个值,不包含"美女"这个值
//在范围内插入成功
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t8 values【挖柳斯】 ("丫丫","女","帅哥,吃");
-- mysql> insert into studb.t8 values("丫丫","女","帅哥,吃");
Query OK, 1 row affected (0.09 sec)
mysql> select【涩莱克特】 * from【弗乱】 studb【斯丢db】.t8;
-- mysql> select * from studb.t8;
+--------+--------+------------+
| 姓名 | 性别 | 爱好 |
+--------+--------+------------+
| 丫丫 | 女 | 帅哥,吃 |
+--------+--------+------------+
1 row in set (0.00 sec)

4.4 练习日期时间类型的使用#

命令操作如下所示:

//建表
mysql> create【克瑞特】 table【忒-部】 studb【斯丢db】.t6(
-> 姓名 char【查尔】(10),
-> 生日 date ,
-> 出生年份 year【耶尔】,
-> 家庭聚会 datetime ,
-> 聚会地点 varchar【瓦儿-查儿】(15),
-> 上班时间 time
-> );
-- mysql> create table studb.t6(
-- -> 姓名 char(10),
-- -> 生日 date,
-- -> 出生年份 year,
-- -> 家庭聚会 datetime,
-- -> 聚会地点 varchar(15),
-- -> 上班时间 time);
Query OK, 0 rows affected (0.25 sec)
//查看表头
mysql> desc studb【斯丢db】.t6 ;
-- mysql> desc studb.t6;
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| 姓名 | char(10) | YES | | NULL | |
| 生日 | date | YES | | NULL | |
| 出生年份 | year | YES | | NULL | |
| 家庭聚会 | datetime | YES | | NULL | |
| 聚会地点 | varchar(15) | YES | | NULL | |
| 上班时间 | time | YES | | NULL | |
+--------------+-------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
//插入表头
mysql> insert【因涩特】 into【因兔】 studb【斯丢db】.t6
-> values【挖柳斯】 ("翠花",20211120,1990,20220101183000,"天坛校区",090000);
-- mysql> insert into studb.t6
-- -> values ("翠花",20211120,1990,20220101183000,"天坛校区",090000);
Query OK, 1 row affected (0.05 sec)
//查看表记录
mysql> select【涩莱克特】 * from【弗乱】 studb【斯丢db】.t6;
-- mysql> select * from studb.t6;
+--------+------------+--------------+---------------------+--------------+--------------+
| 姓名 | 生日 | 出生年份 | 家庭聚会 | 聚会地点 | 上班时间 |
+--------+------------+--------------+---------------------+--------------+--------------+
| 翠花 | 2021-11-20 | 1990 | 2022-01-01 18:30:00 | 天坛校区 | 09:00:00 |
+--------+------------+--------------+---------------------+--------------+--------------+
1 row in set (0.00 sec)

五、表头基本约束#

当前任务环节

flowchart LR
subgraph BottomRow[表结构管理]
direction LR
A[表管理] --> B[表格字段数据类型] --> C[表头基本约束]
end
classDef highlight stroke:#f00,stroke-width:2px;
class C highlight;

约束是一种限制,设置在表头上,用来控制表头的赋值,包括以下几种:

  1. NOT【nuō 特】 NULL【nò】 :非空,用于保证该字段的值不能为空。
  2. DEFAULT【迪-佛特】:默认值,用于保证该字段有默认值。
  3. UNIQUE【U尼克】:唯一索引,用于保证该字段的值具有唯一性,可以为空。
  4. primary【普赖莫瑞】 KEY【kì】:主键,用于保证该字段的值具有唯一性并且非空。
  5. FOREIGN【佛润】 KEY【kì】:外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值,在从表添加外键约束,用于引用主表中某些的值。

5.1 表头不允许赋空值#

//建表时给表头设置默认和不允许赋null【nào】值
mysql> create【克瑞特】 database【得塔-贝斯】 if not【nuō 特】 exists【伊贼谁斯】 db1;
-- mysql> create database if not exists db1;
Query OK, 1 row affected (0.07 sec)
//建表
mysql> create【克瑞特】 table【忒-部】 db1.t31(
-> name char【查尔】(10) not【nuō 特】 null【nào】 ,
-> class【克拉斯】 char【查尔】(7) default【迪-佛特】 "nsd",
-> likes【赖特s】 set【赛特】("money【孟妮】","game","film","music") not【nuō 特】 null【nào】 default【迪-佛特】 "film,music" );
-- mysql> create table db1.t31(
-- -> name char(10) not null,
-- -> class char(7) default "nsd",
-- -> likes set("money","game","film","music") not null default "film,music" );
Query OK, 0 rows affected (0.43 sec)
//查看表头
mysql> desc db1.t31;
-- mysql> desc db1.t31;
+-------+------------------------------------+------+-----+------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------------------------+------+-----+------------+-------+
| name | char(10) | NO | | NULL | |
| class | char(7) | YES | | nsd | |
| likes | set('money','game','film','music') | NO | | film,music | |
+-------+------------------------------------+------+-----+------------+-------+
3 rows in set (0.01 sec)
//验证默认值和不允许为null
mysql> insert【因涩特】 into【因兔】 db1.t31 values【挖柳斯】 (null, null , null);
-- mysql> insert into db1.t31 values(null, null , null);
ERROR 1048 (23000): Column 'name' cannot be null //表头name赋null值 报错
//表头likes【赖特s】赋null值 报错
mysql> insert【因涩特】 into【因兔】 db1.t31 values【挖柳斯】 ("bob", null , null);
-- mysql> insert into db1.t31 values("bob", null , null);
ERROR 1048 (23000): Column 'likes' cannot be null
//符合约束不报错
mysql> insert【因涩特】 into【因兔】 db1.t31 values【挖柳斯】 ("bob",null,"money【孟妮】,game,film");
-- mysql> insert into db1.t31 values("bob",null,"money,game,film");
Query OK, 1 row affected (0.06 sec)
//不赋值的表头使用默认值赋值
mysql> insert【因涩特】 into【因兔】 db1.t31(name) values【挖柳斯】("jim");
-- mysql> insert into db1.t31(name) values("jim");
-- Query OK, 1 row affected (0.01 sec)
//根据需要自定义表头的值
mysql> insert【因涩特】 into【因兔】 db1.t31 values【挖柳斯】 ("lucy","nsd2108","game,film");
-- mysql> insert into db1.t31 values("lucy","nsd2108","game,film");
-- Query OK, 1 row affected (0.14 sec)
//查看表记录
mysql> select【涩莱克特】 * from【弗乱】 db1.t31;
-- mysql> select * from db1.t31;
+------+---------+-----------------+
| name | class | likes |
+------+---------+-----------------+
| bob | NULL | money,game,film |
| jim | nsd | film,music |
| lucy | nsd2108 | game,film |
+------+---------+-----------------+
3 rows in set (0.00 sec)

5.2 表头加唯一索引练习#

唯一索引 (unique【U尼克】)

约束的方式:表头值唯一 , 但可以赋null 值

//建表
create【克瑞特】 table【忒-部】 db1.t32 (姓名 char【查尔】(10) , 护照 char【查尔】(18) unique【U尼克】 );
-- mysql> create table db1.t32 (姓名 char(10) , 护照 char(18) unique);
//查看表头 唯一索引标志UNI
mysql> desc db1.t32 ;
-- mysql> desc db1.t32;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| 姓名 | char(10) | YES | | NULL | |
| 护照 | char(18) | YES | UNI | NULL | |
+--------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)
//赋null值 可以
mysql> insert【因涩特】 into【因兔】 db1.t32 values【挖柳斯】("bob",null);
-- mysql> insert into db1.t32 values("bob",null);
Query OK, 1 row affected (0.07 sec)
//表头值重复不可以
mysql> insert【因涩特】 into【因兔】 db1.t32 values【挖柳斯】("tom","666888");
-- mysql> insert into db1.t32 values("tom","666888");
Query OK, 1 row affected (0.08 sec)
mysql> insert【因涩特】 into【因兔】 db1.t32 values【挖柳斯】("jim","666888");
-- mysql> insert into db1.t32 values("jim","666888");
ERROR 1062 (23000): Duplicate entry '666888' for key【kì】 't32.护照'
//不重复 可以
mysql> insert【因涩特】 into【因兔】 db1.t32 values【挖柳斯】("jim","766888");
-- mysql> insert into db1.t32 values("jim","766888");
Query OK, 1 row affected (0.05 sec)
//查看表记录
mysql> select【涩莱克特】 * from【弗乱】 DB1.t32;
-- mysql> select * from db1.t32;
+------+--------+
| 姓名 | 护照 |
+------+--------+
| bob | NULL |
| tom | 666888 |
| jim | 766888 |
+------+--------+
3 rows in set (0.00 sec)

2 bob nsd2107 bj

3 bob nsd2107 bj

4 bob nsd2107 bj

1)建表

mysql> create【克瑞特】 table【忒-部】 db1.t38 (
-> 行号 int【因特】 primary【普赖莫瑞】 key【kì】 auto_increment【奥特欧_因克瑞门特】 ,
-> 姓名 char【查尔】(10) ,
-> 班级 char【查尔】(7) ,
-> 住址 char【查尔】(10)
-> );
-- mysql> create table db1.t38(
-- -> 行号 int primary key auto_increment,
-- -> 姓名 char(10),
-- -> 班级 char(7),
-- -> 住址 char(10));
Query OK, 0 rows affected (0.76 sec)
//查看表头
mysql> desc db1.t38 ;
-- mysql> desc db1.t38;
+--------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+----------------+
| 行号 | int | NO | PRI | NULL | auto_increment |
| 姓名 | char(10) | YES | | NULL | |
| 班级 | char(7) | YES | | NULL | |
| 住址 | char(10) | YES | | NULL | |
+--------+----------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
//插入表记录 不给自增长表头赋值
mysql> insert【因涩特】 into【因兔】 db1.t38(姓名,班级,住址) values【挖柳斯】("bob","nsd2107","bj");
-- mysql> insert into db1.t38(姓名,班级,住址) values("bob","nsd2107","bj");
Query OK, 1 row affected (0.05 sec)
mysql> insert【因涩特】 into【因兔】 db1.t38(姓名,班级,住址) values【挖柳斯】("bob","nsd2107","bj");
-- mysql> insert into db1.t38(姓名,班级,住址) values("bob","nsd2107","bj");
Query OK, 1 row affected (0.04 sec)
mysql> insert【因涩特】 into【因兔】 db1.t38(姓名,班级,住址) values【挖柳斯】("tom","nsd2107","bj");
-- mysql> insert into db1.t38(姓名,班级,住址) values("tom","nsd2107","bj");
Query OK, 1 row affected (0.05 sec)
//查看表记录
mysql> select【涩莱克特】 * from【弗乱】 db1.t38;
-- mysql> select * from db1.t38;
+--------+--------+---------+--------+
| 行号 | 姓名 | 班级 | 住址 |
+--------+--------+---------+--------+
| 1 | bob | nsd2107 | bj |
| 2 | bob | nsd2107 | bj |
| 3 | tom | nsd2107 | bj |
+--------+--------+---------+--------+
3 rows in set (0.00 sec)

六、作业#

1 选择题#

  1. 在 MySQL 中创建表时,用于定义字段为字符类型且长度为 20 的是以下哪种写法?A A. CHAR(20) B. TEXT(20) C. INT(20) D. FLOAT(20)
讲解:CHAR是固定长度的字符类型,TEXT是可变长度文本类型不能指定长度,INT是整数类型,FLOAT是浮点数类型。
  1. 若要修改表名为 students 的表,将其中 age 字段的数据类型从 INT 改为 SMALLINT,应使用以下哪条语句? B A. UPDATE TABLE students CHANGE age age SMALLINT; B. ALTER TABLE students MODIFY age SMALLINT; C. MODIFY TABLE students ALTER age SMALLINT; D. CHANGE TABLE students UPDATE age SMALLINT;
讲解:使用ALTER TABLE + MODIFY来修改字段数据类型,CHANGE用于修改字段名。
  1. 以下哪种方法可以复制表 orders 的结构和数据到新表 orders_copy ?A A. CREATE TABLE orders_copy AS SELECT * FROM orders; B. COPY TABLE orders TO orders_copy; C. INSERT INTO orders_copy SELECT * FROM orders; D. CLONE TABLE orders orders_copy;
讲解:这是最常用的复制表方法,会同时复制表结构和数据。
  1. 以下适合存储邮件地址的字段类型是?C A. DATE B. DECIMAL C. VARCHAR D. TINYINT
讲解:邮件地址是可变长度字符串,VARCHAR最适合。DATE是日期,DECIMAL是小数,TINYINT是整数。
  1. 要在创建表 products 时,确保 product_name 字段的值不为空,应使用以下哪种约束? B A. UNIQUE B. NOT NULL C. CHECK D. DEFAULT
讲解:NOT NULL约束确保字段必须有值,不能为空。

2 简答题#

  1. 简述在 MySQL 中创建表时,如何选择合适的字段类型,请举例说明。 答: 存储: 身高、体重、工资、奖金,适合使用数值类型。如:tinyint unsigned、long、int 存储: 姓名、家庭地址、收货地址,适合使用字符类型。如:char、varchar 存储: 生日、出生年份、入职时间、下班时间、注册时间,适合使用日期时间。date、time、datetime、year 存储: 爱好、性别、社保医院,适合使用枚举类型。如:enum、set

  2. 说明使用 ALTER TABLE 语句修改表结构时,修改字段名和修改字段数据类型的操作有什么不同。 答: 1. 修改字段数据类型: 语法:alter table 数据库.表 modify 字段名 新数据类型; 2. 修改字段名: 语法:alter table 数据库.表 change 旧字段名 新字段名 数据类型;

  3. 复制表有哪几种常见方式,它们各自的优缺点是什么? 答: 1. 复制表结构(不复制数据) 语法:CREATE TABLE 新表名 LIKE 旧表名; 优点:快速,只复制结构 缺点:不包含数据 2. 复制表结构和数据: 语法:CREATE TABLE 新表名 AS SELECT * FROM 旧表名; 优点:同时复制结构和数据 缺点:不复制索引和约束

  4. 解释表的基本约束 NOT NULLDEFAULT 的作用,并举例说明如何在创建表时使用。 答: NOT NULL: 作用: 不允许字段为空、字段必须有值 举例: create table 数据库.表 (字段名 数据类型 not null); DEFAULT: 作用: 设置字段的默认值、当不赋值时使用 举例: create table 数据库.表 (字段名 数据类型 default 默认值);

3 操作题#

  1. 创建一个名为 books 的表,包含字段 book_title(字符串类型,长度不超过 100)、publish_year(年份类型)、price(小数类型,保留两位小数)。
mysql> create table if not exists studb.books (
-> id int auto_increment primary key,
-> book_title varchar(100),
-> publish_year year,
-> price decimal(10,2)
-> );
Query OK, 0 rows affected (0.94 sec)
mysql> desc studb.books;
+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| book_title | varchar(100) | YES | | NULL | |
| publish_year | year | YES | | NULL | |
| price | decimal(10,2) | YES | | NULL | |
+--------------+---------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql>
  1. books 表中添加一个新字段 author,类型为字符串,长度不超过 50。
mysql>
mysql> alter table studb.books add author varchar(50);
Query OK, 0 rows affected (2.88 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc studb.books;
+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| book_title | varchar(100) | YES | | NULL | |
| publish_year | year | YES | | NULL | |
| price | decimal(10,2) | YES | | NULL | |
| author | varchar(50) | YES | | NULL | |
+--------------+---------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
  1. 复制 books 表的结构和数据到一个新表 books_archive
mysql> create table studb.books_archive select * from studb.books;
Query OK, 0 rows affected (1.29 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show tables;
+-----------------+
| Tables_in_studb |
+-----------------+
| books |
| books_archive |
| salary |
| salary2 |
| stuinfo |
| t1 |
| t2 |
| t6 |
| t8 |
+-----------------+
9 rows in set (0.00 sec)
mysql> desc books_archive;
+--------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+-------+
| id | int | NO | | 0 | |
| book_title | varchar(100) | YES | | NULL | |
| publish_year | year | YES | | NULL | |
| price | decimal(10,2) | YES | | NULL | |
| author | varchar(50) | YES | | NULL | |
+--------------+---------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
  1. 修改 books 表中 price 字段的默认值为 0。
mysql> alter table books modify price decimal(10,2) default 0;
Query OK, 0 rows affected (0.23 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc books;
+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| book_title | varchar(100) | YES | | NULL | |
| publish_year | year | YES | | NULL | |
| price | decimal(10,2) | YES | | 0.00 | |
| author | varchar(50) | YES | | NULL | |
+--------------+---------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql>
  1. books 表中的 book_title 字段设置为不允许为空。
mysql> alter table books modify book_title varchar(100) not null;
Query OK, 0 rows affected (2.19 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc books;
+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| book_title | varchar(100) | NO | | NULL | |
| publish_year | year | YES | | NULL | |
| price | decimal(10,2) | YES | | 0.00 | |
| author | varchar(50) | YES | | NULL | |
+--------------+---------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
05:mysql之表结构管理
https://fuwari.vercel.app/posts/数据库/05-mysql之表结构管理/
作者
肥猫少杰
发布于
2026-06-03
许可协议
CC BY-NC-SA 4.0