系列文章目录
《【MySQL】第一章 MySQL 5.7的安装与卸载》
《【MySQL】第二章 初识数据库》
《【MySQL】第三章 库的操作》
《【MySQL】第四章 表的操作》
《【MySQL】第五章 数据类型》
文章目录
创建表结构
语法介绍
sql
CREATE TABLE [IF NOT EXISTS] table_name (
column_name data_type [column_options] [constraint],
column_name data_type [column_options] [constraint],
...
[table_constraints]
) [[table_options] [table_options]...];
[]
表示可选项。[IF NOT EXISTS]
表示如果表不存在就创建,存在则不会创建。- 字段相关定义
- 字段的相关定义都放在
()
中,且每一类都以,
作为分隔符,最后一列不需要加,
。 column_name
:字段名称,也就是所谓的列名。data_type
:列的数据类型,如int
、varchar
等。column_options
:列的附加选项,如not NULL
、default
、auto_increment
等。constraint
:约束条件,如primary key
、unique
等。
- 字段的相关定义都放在
[table_constraints]
:可选项,表级别约束条件,适用于多个列,如:primary key (column_list)
:定义主键。unique (column_list)
:定义唯一键。foreign key (column_list) references other_table (column_list)
:定义外键。check (expression)
:定义检查约束(MySQL-5.7及以下版本不支持)。
[table_options]
:表选项,用于指定表的存储引擎、字符集、校验集等,如:engine
:指定存储引擎,如InnoDB
、MyISAM
等。default charset
:指定字符集,如utf8
、utf8mb4
。collate
:指定字符集的校验规则,如utf8_general_ci
。auto_increment
:设置自增的起始值。comment
:为表添加注释。
创建表结构的完整语法有点过于复杂,其中涉及到了很多深入学习之后才会了解的知识,这里就先记住下面这个简化版的语法就行,后续的创建表的案例也不会太过于复杂。
sql
CREATE TABLE [IF NOT EXISTS] table_name (
column_name data_type,
column_name data_type,
...
column_name data_type
) charset=字符集 collate=校验集 engin=存储引擎;
创建表结构的案例
sql
create table if not exists user1 (
id int,
name varchar(20) comment '用户名',
password char(32) comment '密码是32位的md5值',
birthday date comment '生日'
) charset=utf8 collate=utf8_general_ci engine=MyISAM;
create table if not exists user2 (
id int,
name varchar(20) comment '用户名',
password char(32) comment '密码是32位的md5值',
birthday date comment '生日'
) charset=utf8 collate=utf8_general_ci engine=innoDB;
- 列的数据类型相关的话题会在后面有独立章节介绍,这里就先用着就行。
int
:指整型数字。varchar(32)
:varchar
长度可变字符串,32是指定最大长度。date
:日期类型。comment
:表示给这一列加上注释。
- 编写创建表结构的SQL语句时,建议带上
[if not exists]
可选项,这样容错率提高。 - 以往出现的SQL语句都是一行写完,但是编写创建表结构的SQL语句时希望可以分成多行来写。
- 因为这里首次正式提到搜索引擎,所以接下来分别创建两张仅搜索引擎的表结构来直观感受一下不同搜索引擎对于表结构的影响。
【engine=MyISAM】
sql
-- 创建user1
mysql> create table if not exists user1 (
-> id int,
-> name varchar(20) comment '用户名',
-> password char(32) comment '密码是32位的md5值',
-> birthday date comment '生日'
-> ) charset=utf8 collate=utf8_general_ci engine=MyISAM;
Query OK, 0 rows affected (0.00 sec)
-- 数据库对应目录下查看表结构
root@iZ7xvhuhaslv4h5dm1d1svZ:/var/lib/mysql/learning# ll
total 28
drwxr-x--- 2 mysql mysql 4096 Oct 31 09:37 ./
drwxr-x--- 7 mysql mysql 4096 Oct 31 09:01 ../
-rw-r----- 1 mysql mysql 61 Oct 24 15:47 db.opt
-rw-r----- 1 mysql mysql 8700 Oct 31 09:37 user1.frm
-rw-r----- 1 mysql mysql 0 Oct 31 09:37 user1.MYD
-rw-r----- 1 mysql mysql 1024 Oct 31 09:37 user1.MYI
【engine=innoDB】
sql
-- 创建user2
mysql> create table if not exists user2 (
-> id int,
-> name varchar(20) comment '用户名',
-> password char(32) comment '密码是32位的md5值',
-> birthday date comment '生日'
-> ) charset=utf8 collate=utf8_general_ci engine=innoDB;
Query OK, 0 rows affected (0.01 sec)
-- 数据库对应目录下查看表结构
root@iZ7xvhuhaslv4h5dm1d1svZ:/var/lib/mysql/learning# ll
total 136
drwxr-x--- 2 mysql mysql 4096 Oct 31 09:37 ./
drwxr-x--- 7 mysql mysql 4096 Oct 31 09:01 ../
-rw-r----- 1 mysql mysql 61 Oct 24 15:47 db.opt
-rw-r----- 1 mysql mysql 8700 Oct 31 09:37 user2.frm
-rw-r----- 1 mysql mysql 98304 Oct 31 09:37 user2.ibd
【对比结果】
创建user1
表指定engine=MyISAM
时,MySQL服务在/var/lib/mysql/learning/
创建了3个文件;
创建user2
表指定engine=innoDB
时,MySQL服务在/var/lib/mysql/learning/
创建了2个文件;
目前关于存储引擎对于表结构的更加详细的影响我们目前不管,我们目前对于存储引擎最直观的感受就是使用了不同的存储引擎,MySQL服务为我们创建表结构时,表文件的数量可能会有差别,表文件的内容也会有差别,目前先记住这一个就好。
查看表结构
查看当前数据库里有哪些表结构
sql
show tables;
示例:
sql
mysql> show tables;
+--------------------+
| Tables_in_learning |
+--------------------+
| user1 |
| user2 |
+--------------------+
2 rows in set (0.00 sec)
查看表结构的详细信息
sql
desc table_name;
示例:
sql
mysql> desc user1;
+----------+-------------+------+-----+---------+-------+
| Field | Type | NULL | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| password | char(32) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
在 DESC user1;
查询结果中,各个字段的含义如下:
列名 | 含义 |
---|---|
Field | 表中的字段名称(列名称)。例如 id 、name 、password 和 birthday 。 |
Type | 字段的数据类型及其长度限制。比如 int(11) 表示整型数据,varchar(20) 表示最多可存储 20 个字符的可变长度字符串。 |
NULL | 是否允许该字段为空 (YES 表示允许为空,NO 表示不允许为空)。 |
Key | 用于标记索引类型。通常有以下几种: - PRI :主键,标识唯一记录 - UNI :唯一索引,保证字段唯一性 - MUL :普通索引,可以重复。 |
Default | 字段的默认值,记录插入时没有赋值的情况下默认填入的值。若为 NULL ,则没有默认值。 |
Extra | 额外属性,常见的有: - auto_increment :表示该字段会自动递增(通常用于主键) - 空白:表示没有特别的额外属性。 |
在 user1
表的具体含义
id
:整型,允许为空,没有索引(即不是主键),默认值为 NULL。name
:长度最多为 20 的字符串,允许为空,没有索引,默认值为 NULL。password
:定长字符串,长度为 32,允许为空,没有索引,默认值为 NULL。birthday
:日期类型,表示出生日期,允许为空,没有索引,默认值为 NULL。
查看表结构的创建
sql
show create table table_name;
示例:
sql
mysql> show create table user2;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| user2 | CREATE TABLE `user2` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL COMMENT '用户名',
`password` char(32) DEFAULT NULL COMMENT '密码是32位的md5值',
`birthday` date DEFAULT NULL COMMENT '生日'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
直接使用show create table user2;
的话会看到SQL语句的执行结构一言难尽。
这是因为当SQL语句以;
结尾时默认以"表格格式"显示,这样的显示方式对于包含许多列的数据及其不友好,因此MySQL还提供了另一种叫做"竖排格式"的显示方式,命令末尾使用 \G
替代分号 ;
即可。
sql
mysql> show create table user2 \G
*************************** 1. row ***************************
Table: user2
Create Table: CREATE TABLE `user2` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL COMMENT '用户名',
`password` char(32) DEFAULT NULL COMMENT '密码是32位的md5值',
`birthday` date DEFAULT NULL COMMENT '生日'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
仔细观察的话能够发现show create table user2;
查询到的创建user2
表的SQL语句和我们之前编写的SQL语句有点出入,因为这是正常的,我们自己编写的SQL语句在MySQL服务的词法分析、语法分析模块来看是不标准的,MySQL服务会将用户输入的不标准的SQL语句转化为标准的格式记录下来,也就是我们查询到的结果。
修改表结构
增加列
sql
alter table table_name add column column_name data_type [AFTER existing_column];
table_name
:表名称,表示你要在该表下新增一列。column_name
:列名称,表示你要新增的那一列的列名称。data_type
:新列的数据类型。data_type
之后其实其实还有附加选项、约束之类的,不过暂时不介绍了。
[AFTER existing_column]
:可选项,显式使用表示将新列插入指定列之后。省略表示将新列添加至表的末尾。
示例:
sql
-- 查看表结构
mysql> desc user1;
+----------+-------------+------+-----+---------+-------+
| Field | Type | NULL | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| password | char(32) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
-- 插入两条数据
mysql> insert into user1 values(1,'a','b','1982-01-04'),(2,'b','c','1984-01-04');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
-- 修改表结构:新增email列
mysql> alter table user1 add column email varchar(50) AFTER name;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
-- 查看修改后的表结构
mysql> desc user1;
+----------+-------------+------+-----+---------+-------+
| Field | Type | NULL | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| email | varchar(50) | YES | | NULL | | <= 这里多了email字段的相关信息
| password | char(32) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
-- 查询修改表结构后的内容
mysql> select * from user1;
+------+------+-------+----------+------------+
| id | name | email | password | birthday |
+------+------+-------+----------+------------+
| 1 | a | NULL | b | 1982-01-04 | <= email列为空,其余没影响
| 2 | b | NULL | c | 1984-01-04 |
+------+------+-------+----------+------------+
2 rows in set (0.00 sec)
修改列
修改列属性
sql
alter table table_name modify column column_name new_data_type;
table_name
:表名称,表明你要对这张表进行修改。modify column
:固定搭配,表明你要对这张表的修改是修改某一列。column_name
:列名称,表明你要修改的列的名称。new_data_type
:列的新数据类型和约束条件。- 修改列的本质是对某一个字段的覆盖式重定义,接下来会举例子说明。
示例:
sql
-- 这是修改前的user1表的创建语句
mysql> show create table user1 \G
*************************** 1. row ***************************
Table: user1
Create Table: CREATE TABLE `user1` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL COMMENT '用户名',
`email` varchar(50) DEFAULT NULL,
`password` char(32) DEFAULT NULL COMMENT '密码是32位的md5值',
`birthday` date DEFAULT NULL COMMENT '生日'
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
-- 将name字段的类型由varchar(20)改为varchar(60)
mysql> alter table user1 modify column name varchar(60);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
-- 这是修改后的user1表的创建语句
mysql> show create table user1 \G
*************************** 1. row ***************************
Table: user1
Create Table: CREATE TABLE `user1` (
`id` int(11) DEFAULT NULL,
`name` varchar(60) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`password` char(32) DEFAULT NULL COMMENT '密码是32位的md5值',
`birthday` date DEFAULT NULL COMMENT '生日'
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
user1
表是在"创建表结构的案例"这一部分内容创建的,当时只写了name varchar(20) comment '用户名'
,表结构被修改前关于name
字段的创建是这样的``name varchar(20) DEFAULT NULL COMMENT '用户名'
,通过对比能够看到DEFAULT NULL
这样的信息都是MySQL服务自动加上的。
而在这个案例中,原本只是打算将name
字段的数据类型由varchar(20)
改为varchar(60)
,并没有打算修改其余部分,但事实上,表结构被修改之后COMMENT '用户名'
这一部分不见了。
前后的对比说明,MySQL是不提供对某一个列的指向性修改的,一旦针对某一个列进行修改就是覆盖式修改,需要重新编写字段的完整的定义,一般的操作操作如下:
- 复制
name varchar(20) comment '用户名'
。 - 改成
name varchar(60) comment '用户名'
。 - 最后写成完整SQL语句
alter table user1 modify column name varchar(60);
。
修改列名称
sql
alter table table_name change column old_column_name new_column_name new_data_type;
table_name
:表名称,表明你要对那张表进行修改。change column
:固定搭配,表明你要对表进行的修改行为是修改列名称。- 虽然明面上是修改列名称,但是个人认为"包括列名称在内对字段进行重定义"这样的解释更为恰当
old_column_name
:旧的列名称,表明要对这个列进行修改。new_column_name
:新的列名称,是修改后的列的名称。new_data_type
:列的新数据类型和约束条件。- 这句SQL语句在用法上和
alter table table_name modify column
是差不多的,都是复制保存,修改,粘贴成修改后的SQL语句,唯一的区别就是提供修改列名称的作用。
示例:
sql
-- 查看user1表的创建语句
mysql> show create table user1 \G
*************************** 1. row ***************************
Table: user1
Create Table: CREATE TABLE `user1` (
`id` int(11) DEFAULT NULL,
`name` varchar(60) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`password` char(32) DEFAULT NULL COMMENT '密码是32位的md5值',
`birthday` date DEFAULT NULL COMMENT '生日'
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
-- 将email列的名称修改为address
-- 个人比较推荐的做法是
-- 1. 输入alter table user1 change column
-- 2. 指定修改email列
-- 3. 复制粘贴`email` varchar(50) DEFAULT NULL
-- 4. 将email修改为address
mysql> alter table user1 change column email `address` varchar(50) DEFAULT NULL;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
-- 查看user1表修改后的创建语句
mysql> show create table user1 \G
*************************** 1. row ***************************
Table: user1
Create Table: CREATE TABLE `user1` (
`id` int(11) DEFAULT NULL,
`name` varchar(60) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`password` char(32) DEFAULT NULL COMMENT '密码是32位的md5值',
`birthday` date DEFAULT NULL COMMENT '生日'
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
删除列
sql
alter table table_name drop column column_name;
table_name
:表名称,表明你要对那张表进行修改。drop column
:固定搭配,表明你要对表进行的修改行为是删除某一列。column_name
:列名称,表明你要删除的列的名称。
示例:
sql
alter table table_name user1 drop column email;
修改表名称
sql
alter table old_table_name rename to new_table_name;
old_table_name
:旧的表名称。new_table_name
:新的表名称。
删除表结构
sql
drop table [if exists] table_name;
drop table
:固定搭配。[if exists]
:可选项,表结构存在则删除,不存在则报一个警告。table_name
:要删除的表的名称。
数据库名称和表名称以及字段等内容不建议随便修改,理由如下:
随意修改表名称和数据库名称对程序员来说是一个巨大的负担,因为这类名称通常不仅仅是表结构的标识符,而是贯穿整个项目、工具链和环境的关键依赖。代码中经常会直接引用表名和数据库名,SQL查询、数据模型、ORM(对象关系映射)都与其紧密相关。一旦名称发生改变,所有这些代码中的引用都要逐一更新,重新测试,这无疑大大增加了工作量。而在实际开发中,表名称和数据库名称往往会被外部系统或服务引用,比如报表系统、自动化任务、数据仓库和监控系统等,一次更改就意味着这些所有的相关依赖都要进行更新和重新适配。因此,表名或数据库名的修改往往不只是一个简单的字符串替换,它会触发一连串的更改需求,涉及代码、测试环境、生产环境的一致性调整,且容易出错,带来额外的维护成本。
此外,数据库结构的更改通常受版本控制管理,在多团队协作和持续集成的项目中,频繁的结构变动会引发分支的版本冲突,带来版本管理上的难题,最终影响项目稳定性。这种频繁变动还会导致开发、测试和生产环境不一致,使问题排查变得更加复杂。为了避免这种情况,通常在设计数据库结构时会提前做好规划,确保名称的清晰性和模块化,这样能在后续的开发中避免随意修改带来的繁琐与不稳定。