第5章、表的基本操作
标签: MySQL是怎样使用的新版
数据库建好之后,我们就可以接着创建真正存储数据的表了。创建表的时候首先需要描述清楚这个表长什么样,它有哪些列,这些列都是用来存什么类型的数据等等,这个对表的描述称为表的结构或者定义。有了表的结构之后,我们就可以着手把数据塞到这个表里了。表中的一行叫做一条记录,一列叫做一个字段。
展示当前数据库中的表
下边的语句用于展示当前数据库中有哪些表:
SHOW TABLES;
我们的当前数据库是xiaohaizi,然后用上述语句查看下xiaohaizi数据库中都有哪些表:
mysql> SHOW TABLES;Empty set (0.00 sec)mysql>
很抱歉,当前xiaohaizi数据库中一个表也没有,所以得到的结果就是Empty set。我们赶紧在当前数据库中创建几个表噻。
创建表
基本语法
创建一个表时至少需要完成下列事情:
- 给表起个名。
- 给表定义一些列,并且给这些列都起个名。
- 每一个列都需要定义一种数据类型。
- 如果有需要的话,可以给这些列定义一些列的属性,比如不许存储
NULL,设置默认值等等,具体列可以设置哪些属性我们稍后详细唠叨。
MySQL中创建表的基本语法就是这样的:
CREATE TABLE 表名 (列名1 数据类型 [列的属性],列名2 数据类型 [列的属性],...列名n 数据类型 [列的属性]);
也就是说:
在
CREATE TABLE后写清楚我们要创建的表的名称。然后在小括号
()中定义上这个表的各个列的信息,包括列的名称、列的数据类型,如果有需要的话也可以定义这个列的属性(列的属性用中括号[]引起来的意思就是这部分是可选的,也就是可有可无的)。列名、数据类型、列的属性之间用空白字符分开就好,然后各个列的信息之间用逗号
,分隔开。
小贴士: 我们也可以把这个创建表的语句都放在单行中,而示例中将建表语句分成多行并且加上缩进仅仅是为了美观而已~
废话不多说,赶紧定义一个超级简单的表瞅瞅:
CREATE TABLE first_table (first_column INT,second_column VARCHAR(100));
这个表的名称叫做first_table,它有两个列:
第一个列的名称是
first_column,它的数据类型是INT,意味着只能存放整数。第二个列的名称是
second_column,它的数据类型是VARCHAR(100),意味着这个列可以存放长度不超过100个字符的字符串。
我们在客户端执行一下这个语句(当前数据库是xiaohaizi):
mysql> CREATE TABLE first_table (-> first_column INT,-> second_column VARCHAR(100)-> );Query OK, 0 rows affected (0.02 sec)mysql>
输出Query OK, 0 rows affected (0.02 sec)意味着创建成功了,并且耗时0.02秒。
为建表语句添加注释
我们可以在创建表时将该表的用处以注释的形式添加到语句中,只要在建表语句最后加上COMMENT语句就好,如下:
CREATE TABLE 表名 (各个列的信息 ...) COMMENT '表的注释信息';
比如我们可以这样写first_table表的建表语句:
CREATE TABLE first_table (first_column INT,second_column VARCHAR(100)) COMMENT '第一个表';
注释没必要太长,言简意赅即可,毕竟是给人看的,让人看明白是个啥意思就好了。为了我们自己的方便,也为了阅读你创建的人的方便,请遵守一下职业道德,写个注释吧~
创建现实生活中的表
有了创建first_table的经验,我们就可以着手用MySQL把之前提到的学生基本信息表和成绩表给创建出来了,先把学生基本信息表搬下来看看:
学生基本信息表
| 学号 | 姓名 | 性别 | 身份证号 | 学院 | 专业 | 入学时间 |
|---|---|---|---|---|---|---|
| 20180101 | 杜子腾 | 男 | 158177199901044792 | 计算机学院 | 计算机科学与工程 | 2018/9/1 |
| 20180102 | 杜琦燕 | 女 | 151008199801178529 | 计算机学院 | 计算机科学与工程 | 2018/9/1 |
| 20180103 | 范统 | 男 | 17156319980116959X | 计算机学院 | 软件工程 | 2018/9/1 |
| 20180104 | 史珍香 | 女 | 141992199701078600 | 计算机学院 | 软件工程 | 2018/9/1 |
很显然,这个表有学号、姓名、性别、身份证号、学院、专业、入学时间这几个列,其中的学号是整数类型的,入学时间是日期类型的,由于身份证号是固定的18位,我们可以把身份证号这一列定义成固定长度的字符串类型,性别一列只能填男或女,所以我们这里把它定义为ENUM类型的,其余各个列都是变长的字符串类型。看一下创建学生基本信息表的语句:
CREATE TABLE student_info (number INT,name VARCHAR(5),sex ENUM('男', '女'),id_number CHAR(18),department VARCHAR(30),major VARCHAR(30),enrollment_time DATE) COMMENT '学生基本信息表';
然后再看一下学生成绩表:
学生成绩表
| 学号 | 科目 | 成绩 |
|---|---|---|
| 20180101 | 母猪的产后护理 | 78 |
| 20180101 | 论萨达姆的战争准备 | 88 |
| 20180102 | 母猪的产后护理 | 100 |
| 20180102 | 论萨达姆的战争准备 | 98 |
| 20180103 | 母猪的产后护理 | 59 |
| 20180103 | 论萨达姆的战争准备 | 61 |
| 20180104 | 母猪的产后护理 | 55 |
| 20180104 | 论萨达姆的战争准备 | 46 |
这个表有学号、科目、成绩这几个列,学号和成绩是整数类型的,科目是字符串类型的,所以我们可以这样写建表语句:
CREATE TABLE student_score (number INT,subject VARCHAR(30),score TINYINT) COMMENT '学生成绩表';
待这几个表创建成功之后,我们使用SHOW TABLES语句看一下当前数据库(xiaohaizi数据库)中有哪些表:
mysql> SHOW TABLES;+---------------------+| Tables_in_xiaohaizi |+---------------------+| first_table || student_info || student_score |+---------------------+3 rows in set (0.01 sec)mysql>
我们刚才创建的表就都被展示出来了。赶紧到你自己的客户端里填写这些语句吧~
IF NOT EXISTS
和重复创建数据库一样,如果创建一个已经存在的表的话是会报错的,我们来试试重复创建一下first_table表:
mysql> CREATE TABLE first_table (-> first_column INT,-> second_column VARCHAR(100)-> ) COMMENT '第一个表';ERROR 1050 (42S01): Table 'first_table' already existsmysql>
执行结果提示了一个ERROR,意思是first_table已经存在!所以如果想要避免这种错误发生,可以在创建表的时候使用这种形式:
CREATE TABLE IF NOT EXISTS 表名(各个列的信息 ...);
加入了IF NOT EXISTS的语句表示如果指定的表名不存在则创建这个表,如果存在那就什么都不做。我们使用这种IF NOT EXISTS的语法再来执行一遍创建first_table表的语句:
mysql> CREATE TABLE IF NOT EXISTS first_table (-> first_column INT,-> second_column VARCHAR(100)-> ) COMMENT '第一个表';Query OK, 0 rows affected, 1 warning (0.00 sec)mysql>
可以看到语句执行成功了,只是结果中有1个warning而已。
删除表
如果我们觉得某个表以后都用不到了,就可以把它删除掉。在真实工作环境中删除表一定要慎重谨慎,失去了的就再也回不来了~ 看一下删除的语法:
DROP TABLE 表1, 表2, ..., 表n;
也就是说我们可以同时删除多个表。我们现在把first_table表给删掉看看:
mysql> DROP TABLE first_table;Query OK, 0 rows affected (0.01 sec)mysql> SHOW TABLES;+---------------------+| Tables_in_xiaohaizi |+---------------------+| student_info || student_score |+---------------------+2 rows in set (0.00 sec)mysql>
可以看到现在数据库xiaohaizi中没有了first_table表,说明删除成功了!
IF EXISTS
如果我们尝试删除某个不存在的表的话会报错:
mysql> DROP TABLE first_table;ERROR 1051 (42S02): Unknown table 'xiaohaizi.first_table'mysql>
执行结果提示了一个ERROR,提示我们要删除的表并不存在,如果想避免报错,可以使用这种删除语法:
DROP TABLE IF EXISTS 表名;
然后再删除一下不存在的first_table表:
mysql> DROP TABLE IF EXISTS first_table;Query OK, 0 rows affected, 1 warning (0.00 sec)mysql>
这样就不报错了~
查看表结构
有时候我们可能忘记了自己定义的表的结构,可以使用下边这些语句来查看,它们起到的效果都是一样的:
DESCRIBE 表名;DESC 表名;EXPLAIN 表名;SHOW COLUMNS FROM 表名;SHOW FIELDS FROM 表名;
比如我们看一下student_info这个表的结构:
mysql> DESC student_info;+-----------------+-------------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-----------------+-------------------+------+-----+---------+-------+| number | int(11) | YES | | NULL | || name | varchar(5) | YES | | NULL | || sex | enum('男','女') | YES | | NULL | || id_number | char(18) | YES | | NULL | || department | varchar(30) | YES | | NULL | || major | varchar(30) | YES | | NULL | || enrollment_time | date | YES | | NULL | |+-----------------+-------------------+------+-----+---------+-------+7 rows in set (0.00 sec)mysql>
可以看到,这个student_info表的各个列的名称、类型和属性就都展示出来了。当然我们现在还未学习过列的属性(我们下一章才会唠叨),所以我们现在只需要看结果中的Field和Type列就好了。
如果你看不惯这种以表格的形式展示各个列信息的方式,我们还可以使用下边这个语句来查看表结构:
SHOW CREATE TABLE 表名;
比如:
mysql> SHOW CREATE TABLE student_info;+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Table | Create Table |+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| student_info | CREATE TABLE `student_info` (`number` int(11) DEFAULT NULL,`name` varchar(5) DEFAULT NULL,`sex` enum('男','女') DEFAULT NULL,`id_number` char(18) DEFAULT NULL,`department` varchar(30) DEFAULT NULL,`major` varchar(30) DEFAULT NULL,`enrollment_time` date DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生基本信息表' |+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set (0.00 sec)mysql>
由于这行数据太长了,所以输出效果并不是很好,我们可以把原来用于标记语句结束的分号;改为\G,以垂直的方式展示每一列数据的效果可能好点:
mysql> SHOW CREATE TABLE student_info\G*************************** 1. row ***************************Table: student_infoCreate Table: CREATE TABLE `student_info` (`number` int(11) DEFAULT NULL,`name` varchar(5) DEFAULT NULL,`sex` enum('男','女') DEFAULT NULL,`id_number` char(18) DEFAULT NULL,`department` varchar(30) DEFAULT NULL,`major` varchar(30) DEFAULT NULL,`enrollment_time` date DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生基本信息表'1 row in set (0.00 sec)mysql>
可以看到,使用SHOW CREATE TABLE这个语句展示出来的表结构就是我们平时创建表的语句,而且为各个列自动的添加了一些我们还没有唠叨过的属性(现在不要纠结那些属性的含义,我们稍后再讲)。
小贴士: 你可能疑惑的是在表定义末尾的ENGINE=InnoDB DEFAULT CHARSET=utf8是什么意思,这个是指定表的存储引擎和默认字符集,这些内容并不是零基础小白应该学习的内容,有兴趣的同学可以到《MySQL是怎样运行的:从根儿上理解MySQL》中去了解,大家现在不用关心~
没有选择当前数据库时对表的操作
有时候我们并没有使用USE语句来选择当前数据库,或者在一条语句中遇到的表分散在不同的数据库中,如果我们想在语句中使用这些表,那么就必须显式的指定这些表所属的数据库了。比如不管当前数据库是不是xiaohaizi,我们都可以调用这个语句来展示数据库xiaohaizi里边的表:
mysql> SHOW TABLES FROM xiaohaizi;+---------------------+| Tables_in_xiaohaizi |+---------------------+| first_table || student_info || student_score |+---------------------+3 rows in set (0.00 sec)mysql>
其他地方如果使用到表名的话,需要显式指定这个表所属的数据库,指明方式是这样的:
数据库名.表名
比方说我们想查看xiaohaizi数据库下first_table表的结构,但是又没有使用USE xiaohaizi语句指定当前数据库,此时可以这样写语句:
SHOW CREATE TABLE xiaohaizi.first_table\G
修改表
在表创建好之后如果对表的结构不满意,比如想增加或者删除一列,想修改某一列的数据类型或者属性,想对表名或者列名进行重命名,这些操作统统都算是修改表结构。MySQL给我们提供了一系列修改表结构的语句。
修改表名
我们可以通过下边这两种方式来修改表的名称:
方式一:
ALTER TABLE 旧表名 RENAME TO 新表名;
我们把`first_table`表的名称修改为`first_table1`(当前数据库为`xiaohaizi`):mysql> ALTER TABLE first_table RENAME TO first_table1;Query OK, 0 rows affected (0.01 sec)mysql> SHOW TABLES;+---------------------+| Tables_in_xiaohaizi |+---------------------+| first_table1 || student_info || student_score |+---------------------+3 rows in set (0.00 sec)mysql>通过`SHOW TABLES`命令可以看到已经改名成功了。
方式二:
RENAME TABLE 旧表名1 TO 新表名1, 旧表名2 TO 新表名2, ... 旧表名n TO 新表名n;
这种改名方式的牛逼之处就是它可以在一条语句中修改多个表的名称。这里就不举例了,自己测试一下吧。
如果在修改表名的时候指定了数据库名,还可以将该表转移到对应的数据库下,比方说我们先再创建一个数据库dahaizi:
mysql> CREATE DATABASE dahaizi;Query OK, 1 row affected (0.00 sec)mysql>
然后把first_table1表转移到这个dahaizi数据库下:
mysql> ALTER TABLE first_table1 RENAME TO dahaizi.first_table1;Query OK, 0 rows affected (0.01 sec)mysql> SHOW TABLES FROM dahaizi;+-------------------+| Tables_in_dahaizi |+-------------------+| first_table1 |+-------------------+1 row in set (0.00 sec)mysql> SHOW TABLES FROM xiaohaizi;+---------------------+| Tables_in_xiaohaizi |+---------------------+| student_info || student_score |+---------------------+2 rows in set (0.00 sec)mysql>
可以看到first_table1就从数据库xiaohaizi转移到dahaizi里边了。我们再用修改表名的方式二再把该表转移到xiaohaizi数据库中,并且将其更名为first_table:
mysql> RENAME TABLE dahaizi.first_table1 TO xiaohaizi.first_table;Query OK, 0 rows affected (0.00 sec)mysql>
增加列
我们可以使用下边的语句来增加表中的列:
ALTER TABLE 表名 ADD COLUMN 列名 数据类型 [列的属性];
比如我们向first_table里添加一个名叫third_column的列就可以这么写:
mysql> ALTER TABLE first_table ADD COLUMN third_column CHAR(4) ;Query OK, 0 rows affected (0.05 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`first_column` int(11) DEFAULT NULL,`second_column` varchar(100) DEFAULT NULL,`third_column` char(4) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.01 sec)mysql>
通过查看表的结构可以看到third_column列已经添加成功了。
增加列到特定位置
默认的情况下列都是加到现有列的最后一列后面,我们也可以在添加列的时候指定它的位置,常用的方式如下:
添加到第一列:
ALTER TABLE 表名 ADD COLUMN 列名 列的类型 [列的属性] FIRST;
让我们把`fourth_column`插入到第一列:mysql> ALTER TABLE first_table ADD COLUMN fourth_column CHAR(4) FIRST;Query OK, 0 rows affected (0.04 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`fourth_column` char(4) DEFAULT NULL,`first_column` int(11) DEFAULT NULL,`second_column` varchar(100) DEFAULT NULL,`third_column` char(4) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.01 sec)mysql>看到插入成功了。
添加到指定列的后边:
ALTER TABLE 表名 ADD COLUMN 列名 列的类型 [列的属性] AFTER 指定列名;
再插入一个`fifth_column`到`first_column`后边瞅瞅:mysql> ALTER TABLE first_table ADD COLUMN fifth_column CHAR(4) AFTER first_column;Query OK, 0 rows affected (0.03 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`fourth_column` char(4) DEFAULT NULL,`first_column` int(11) DEFAULT NULL,`fifth_column` char(4) DEFAULT NULL,`second_column` varchar(100) DEFAULT NULL,`third_column` char(4) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.00 sec)mysql>可以看到`fifth_column`列就被插到`first_column`列后边了。
删除列
我们可以使用下边的语句来删除表中的列:
ALTER TABLE 表名 DROP COLUMN 列名;
我们把刚才向first_table里添加几个列都删掉试试:
mysql> ALTER TABLE first_table DROP COLUMN third_column;Query OK, 0 rows affected (0.05 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> ALTER TABLE first_table DROP COLUMN fourth_column;Query OK, 0 rows affected (0.05 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> ALTER TABLE first_table DROP COLUMN fifth_column;Query OK, 0 rows affected (0.04 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`first_column` int(11) DEFAULT NULL,`second_column` varchar(100) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.00 sec)mysql>
从结果中可以看出third_column、fourth_column、fifth_column这几个列都被删除了。
修改列信息
修改列的信息有下边这两种方式:
方式一:
ALTER TABLE 表名 MODIFY 列名 新数据类型 [新属性];
我们来修改一下`first_table`表的`second_column`列,把它的数据类型修改为`VARCHAR(2)`:mysql> ALTER TABLE first_table MODIFY second_column VARCHAR(2);Query OK, 0 rows affected (0.04 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`first_column` int(11) DEFAULT NULL,`second_column` varchar(2) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.00 sec)mysql>可以看到`second_column`的数据类型就已经被修改为`VARCHAR(2)`了。不过在修改列信息的时候需要注意:修改后的数据类型和属性一定要兼容表中现有的数据!比方说原先`first_table`表的类型是`VARCHAR(100)`,该类型最多能存储100个字符,如果表中的某条记录的`second_column`列值为`'aaa'`,也就是占用了3个字符,而此时我们尝试使用上边的语句将`second_column`列的数据类型修改为`VARCHAR(2)`,那么此时就会报错,因为`VARCHAR(2)`并不能存储3个字符。
方式二:
ALTER TABLE 表名 CHANGE 旧列名 新列名 新数据类型 [新属性];
可以看到这种修改方式需要我们填两个列名,也就是说在修改数据类型和属性的同时也可以修改列名!比如我们修改`second_column`的列名为`second_column1`:mysql> ALTER TABLE first_table CHANGE second_column second_column1 VARCHAR(2)\GQuery OK, 0 rows affected (0.04 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`first_column` int(11) DEFAULT NULL,`second_column1` varchar(2) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.00 sec)mysql>可以看到结果中`second_column`的列名已经被修改为了`second_column1`,不过我们并没有改动该列的数据类型和属性,所以直接把旧的数据类型和属性抄过来就好了。
修改列排列位置
如果我们觉得当前列的顺序有问题的话,可以使用下边这几条语句进行修改:
将列设为表的第一列:
ALTER TABLE 表名 MODIFY 列名 列的类型 列的属性 FIRST;
先看一下现在表`first_table`的各个列的排列顺序:mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`first_column` int(11) DEFAULT NULL,`second_column1` varchar(2) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.00 sec)mysql>可以看到,列的顺序依次是:`first_column`、`second_column1`。现在我们想把`second_column`放在第一列可以这么写:mysql> ALTER TABLE first_table MODIFY second_column1 VARCHAR(2) FIRST;Query OK, 0 rows affected (0.02 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`second_column1` varchar(2) DEFAULT NULL,`first_column` int(11) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.00 sec)mysql>看到`second_column1`已经成为第一列了!
将列放到指定列的后边:
ALTER TABLE 表名 MODIFY 列名 列的类型 列的属性 AFTER 指定列名;
比方说我们想把`second_column1`再放到`first_column`后边可以这么写:mysql> ALTER TABLE first_table MODIFY second_column1 VARCHAR(2) AFTER first_column;Query OK, 0 rows affected (0.03 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SHOW CREATE TABLE first_table\G*************************** 1. row ***************************Table: first_tableCreate Table: CREATE TABLE `first_table` (`first_column` int(11) DEFAULT NULL,`second_column1` varchar(2) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='第一个表'1 row in set (0.00 sec)mysql>
一条语句中包含多个修改操作
如果对同一个表有多个修改操作的话,我们可以把它们放到一条语句中执行,就像这样:
ALTER TABLE 表名 操作1, 操作2, ..., 操作n;
上边我们在演示删除列操作的时候用三条语句连着删了third_column、fourth_column和fifth_column这三个列,其实这三条语句可以合并为一条:
ALTER TABLE first_table DROP COLUMN third_column, DROP COLUMN fourth_column, DROP COLUMN fifth_column;
这样人敲的语句也少了,服务器也不用分多次执行从而效率也高了,何乐而不为呢?
