标签: MySQL入门mysql
MySQL
使用表来存放数据,表的每一列都须要存放特定格式的数据,因此MySQL
为不一样的格式的数据定义了不一样的类型,咱们介绍了各类数值、字符串、时间和二进制类型的含义以及要求的存储空间。本集来看一下在MySQL
中关于数据库和表的各类操做。程序员
咱们知道MySQL
的基本运行过程就是:经过客户端程序发送命令给服务器程序,服务器程序按照接收的命令去操做实际的数据。在咱们使用黑框框启动了MySQL
客户端程序以后,界面上会一直显示一行mysql>
的提示符,你能够在它后边输入咱们的命令而后按一下回车键,在书写命令的时候须要注意下边这几点:sql
命令结束符号。数据库
在书写完一个命令以后须要如下边这几个符号之一结尾:bash
;
\g
\G
好比说咱们执行一个简单的查询当前时间的命令:服务器
mysql> SELECT NOW();
+---------------------+
| NOW() |
+---------------------+
| 2018-02-06 17:50:55 |
+---------------------+
1 row in set (0.00 sec)
mysql>
复制代码
其中的SELECT
意味着这是一个查询命令,NOW()
是MySQL
内置的函数,用于返回当前时间。不过咱们如今并非深究具体的某个命令是什么意思,只是想介绍一下书写命令时须要注意的一些事情。结果中1 row in set (0.00 sec)
的意思是结果只有1行数据,用时0.00秒。使用\g
能够起到同样的效果:函数
mysql> SELECT NOW()\g
+---------------------+
| NOW() |
+---------------------+
| 2018-02-06 17:50:55 |
+---------------------+
1 row in set (0.00 sec)
mysql>
复制代码
\G
有一点特殊,它并不以表格的形式返回查询数据,而是以垂直
的形式展示查询数据:学习
mysql> SELECT NOW()\G
*************************** 1. row ***************************
NOW(): 2018-02-06 17:51:51
1 row in set (0.00 sec)
mysql>
复制代码
若是查询结果很是长的话,使用\G
可让咱们看清结果。若是显式格式没啥问题,那咱们平时都使用分号;
做为命令结束符了~。测试
命令能够随意换行。优化
并非按了回车键就提交命令了,只要按回车键的时候输入的语句里没有;
、\g
或者\G
就算是语句没结束。好比上边查询当前时间的命令还能够这么写:
mysql> SELECT
-> NOW()
-> ;
+---------------------+
| NOW() |
+---------------------+
| 2018-02-06 17:57:15 |
+---------------------+
1 row in set (0.00 sec)
mysql>
复制代码
能够一次提交多个命令
咱们能够在一条语句里写多个命令(命令之间用上面说的结束符分隔),好比这样:
mysql> SELECT NOW(); SELECT NOW(); SELECT NOW();
+---------------------+
| NOW() |
+---------------------+
| 2018-02-06 18:00:05 |
+---------------------+
1 row in set (0.00 sec)
+---------------------+
| NOW() |
+---------------------+
| 2018-02-06 18:00:05 |
+---------------------+
1 row in set (0.00 sec)
+---------------------+
| NOW() |
+---------------------+
| 2018-02-06 18:00:05 |
+---------------------+
1 row in set (0.00 sec)
mysql>
复制代码
连着输入了3个查询当前时间的命令,只要没按回车键,就不会提交命令。
小贴士: 后边咱们还会介绍把命令都写在文件里,而后再批量执行文件中的命令,那个感受更爽!
使用\c
清除本次操做。
若是你想放弃本次编写的命令,可使用\c
来清除,好比这样:
mysql> SELECT NOW()\c
mysql>
复制代码
若是不使用\c
,那客户端会觉得这是一个多行命令,还在一直傻傻的等你输入命令~
大小写问题。
MySQL
默认对命令的大小写并无限制,也就是说咱们这样查询当前时间也是能够的:
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2018-02-06 18:23:01 |
+---------------------+
1 row in set (0.00 sec)
mysql>
复制代码
不过按照习俗,这些命令、函数什么的都是要大写的,而一些名称类的东西,好比数据库名,表名、列名啥的都是要小写的,更多具体的书写规范等咱们遇着再详细介绍。
字符串的表示。
在命令里有时会使用到字符串,咱们可使用单引号''
或者双引号""
把字符串内容引发来,好比这样:
mysql> SELECT 'aaa';
+-----+
| aaa |
+-----+
| aaa |
+-----+
1 row in set (0.00 sec)
mysql>
复制代码
这个语句只是简单的把字符串'aaa'
又输出来了而已。可是必定要在字符串内容上加上引号,否则的话MySQL
服务器会把它看成列名,好比这样就会返回一个错误:
mysql> SELECT aaa;
ERROR 1054 (42S22): Unknown column 'aaa' in 'field list'
mysql>
复制代码
可是MySQL
中有一种叫ANSI_QUOTES
的模式,若是开启了这种模式,双引号就有其余特殊的用途了,可能你并不能看懂我在说什么,可是这都不重要,重要的是建议你最好使用单引号来表示字符串~
当一条命令发送给了MySQL服务器以后,服务器处理完后就会给你发送回来响应的结果,而后显示到界面上。而后你就能够接着输入下一条命令了。
MySQL
中把某种类型的表的集合称为一个数据库
,MySQL
服务器管理着若干个数据库,每一个数据库下均可以有若干个表,画个图就是这样:
在咱们刚刚安装好MySQL
的时候,它已经内建了许多数据库和表了,咱们可使用下边这个命令来看一下都有哪些数据库:
SHOW DATABASES;
复制代码
我本身的电脑上安装的MySQL
版本是5.7.21
,看一下在这个版本里内建了哪些数据库(启动客户端软件,用你的用户名和密码登陆后输入命令):
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
mysql>
复制代码
能够看到,这一版本的MySQL
已经为咱们内建了4个数据库,这些数据库都是给MySQL
本身使用的,若是咱们想使用MySQL
存放本身的数据的话,首先须要建立一个属于本身的数据库。
建立数据库的语法贼简单:
CREATE DATABASE 数据库名;
复制代码
来实际操做一下:
mysql> CREATE DATABASE xiaohaizi;
Query OK, 1 row affected (0.00 sec)
mysql>
复制代码
我把个人名字xiaohaizi
做为了数据库名称,敲完命令回车以后提示了一个Query OK, 1 row affected (0.00 sec)
说明数据库建立成功了。而后咱们再用SHOW DATABASES
的命令查看一下如今有哪些数据库:
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| xiaohaizi |
+--------------------+
5 rows in set (0.00 sec)
mysql>
复制代码
看到咱们本身建立的数据库xiaohaizi
就已经在列表里了。
咱们在一个数据库已经存在的状况下再使用CREATE DATABASE
去建立这个数据库会产生错误:
mysql> CREATE DATABASE xiaohaizi;
ERROR 1007 (HY000): Can't create database 'xiaohaizi'; database exists mysql> 复制代码
执行结果提示了一个ERROR
,意思是数据库xiaohaizi
已经存在!因此若是咱们并不清楚数据库是否存在,可使用下边的语句来建立数据库:
CREATE DATABASE IF NOT EXISTS 数据库名;
复制代码
这个命令的意思是若是指定的数据库不存在的话就建立它,不然什么都不作。咱们试一试:
mysql> CREATE DATABASE IF NOT EXISTS xiaohaizi;
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql>
复制代码
能够看到语句执行成功了,报的ERROR
错误也没有了,只是结果中有1个warning
而已。这个warning
只是MySQL
善意的提醒咱们数据库xiaohaizi
不存在而已,并不会影响语句的执行。
小贴士: 前边说过MySQL的命令能够多条一块儿执行,能够在黑框框中一次输入多个命令,也能够把好多命令放到一个文件中执行。若是某一条命令的执行结果是产生了一个`ERROR`,MySQL会中止执行该命令以后的命令,可是若是仅仅是在执行结果中有`warning`的话,是不会中断执行的。
对于每个链接到MySQL
服务器的客户端,都有一个当前数据库的概念,咱们建立的表默认都会被放到当前数据库中,切换当前数据库的命令也贼简单:
USE 数据库名称;
复制代码
因此在介绍建立表以前,咱们应该把当前数据库切换到刚刚建立的数据库xiaohaizi
上:
mysql> USE xiaohaizi;
Database changed
mysql>
复制代码
看到显示了Database changed
说明当前数据库已经切换成功了。须要注意的是,在退出当前客户端以后,也就是你输入了exit
或者quit
命令以后或者直接把当前的黑框框页面关掉,当你再次调用mysql -h 主机名 -u 用户名 -p 密码
的时候,至关于从新开启了一个客户端,须要从新调用USE 数据库名称
的命令来选择一下当前数据库。
若是你建立的数据库没用了,咱们还能够把它删掉,语法以下:
DROP DATABASE 数据库名;
复制代码
在真实的工做环境里,在删除数据库以前你须要先拿体温计量量是否是发高烧了,而后再找至少两我的核实一下本身是否是发烧了,而后你才敢执行删除数据库的命令。删除数据库意味着里边的表就都被删除了,也就意味着你的数据都没了,因此是个极其危险的操做,使用时须要极其谨慎。不过咱们这是学习环境,并且刚刚建立了xiaohaizi
数据库,什么表都没往里头放,删了就删了吧:
mysql> DROP DATABASE xiaohaizi;
Query OK, 0 rows affected (0.01 sec)
mysql>
复制代码
而后看一下如今还有哪些数据库:
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
mysql>
复制代码
能够看到咱们前边建立的xiaohaizi
数据库就没有啦。
若是某个数据库并不存在,咱们仍旧调用DROP TABLE
语句去删除它,会报错的:
mysql> DROP DATABASE xiaohaizi;
ERROR 1008 (HY000): Can't drop database 'xiaohaizi'; database doesn't exist
mysql>
复制代码
若是想避免这种报错,可使用这种形式的语句来删除数据库:
DROP DATABASE IF EXISTS 表名;
复制代码
再次删除一下xiaohaizi
:
mysql> DROP DATABASE IF EXISTS xiaohaizi;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql>
复制代码
这回就不会报错啦!演示完删除数据库的流程以后仍是把xiaohaizi
数据库建立出来而且切换到当前数据库吧,毕竟咱们以后还要在这个数据库里建立各类表呢~
数据库建好以后,咱们就能够接着建立真正存储数据的表了。建立表的时候首先须要描述清楚这个表长什么样,它有哪些列,这些列都是用来存什么类型的数据等等,这个对表的描述称为表的模式
(scheme
)。有了表的模式以后,咱们就能够着手把数据塞到这个表里了。表中的每一行也叫作一条记录
,每一列也叫作一个字段
。
建立一个表须要至少要完成下列事情:
约束性条件
,具体有哪些列的属性咱们稍后会详细唠叨。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秒。
有了建立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
);
复制代码
而后再看一下学生成绩表:
学号 | 科目 | 成绩 |
---|---|---|
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
);
复制代码
赶忙到你的客户端里填写建立这两个表的命令吧~
咱们刚才在xiaohaizi
数据库里建立了几个表,那咱们怎么查看xiaohaizi
数据库下都有哪些表呢?MySQL
提供了这样的一个命令:
SHOW TABLES;
复制代码
该命令会展现出当前数据库中都有哪些表,咱们执行一下:
mysql> show tables;
+---------------------+
| Tables_in_xiaohaizi |
+---------------------+
| first_table |
| student_info |
| student_score |
+---------------------+
3 rows in set (0.01 sec)
mysql>
复制代码
咱们刚才建立的表就都被展现出来了。
和重复建立数据库同样,若是建立一个已经存在的表的话是会报错的,咱们来试试重复建立一下first_table
表:
mysql> CREATE TABLE first_table (
-> first_column INT,
-> second_column VARCHAR(100)
-> );
ERROR 1050 (42S01): Table 'first_table' already exists
mysql>
复制代码
执行结果提示了一个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)
-> );
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql>
复制代码
能够看到语句执行成功了,报的ERROR
错误也没有了,只是结果中有1个warning
而已。
在建立完表以后,咱们只是建立了一个壳子,里边什么数据都没有。使用表的目的固然是存储数据啦,下边咱们来看几个简单的查询与插入语句,更多关于表中数据的操做语句咱们以后会详细唠叨的。
若是咱们想查看某个表里已经存储了哪些数据,能够用下边这个语句:
SELECT * FROM 表名;
复制代码
好比咱们想看看前边建立的first_table
表中有哪些数据,能够这么写:
mysql> SELECT * FROM first_table;
Empty set (0.01 sec)
mysql>
复制代码
很遗憾,咱们历来没有向表中插入过数据,因此查询结果显示的是Empty set
,表示什么都没查出来~
MySQL
插入数据的时候是以行为单位的,语法格式以下:
INSERT INTO 表名(列1, 列2, ...) VALUES(列1的值,列2的值, ...);
复制代码
也就是说咱们能够在表名后边的括号中指定要插入数据的列,而后在VALUES
后边的括号中按指定的列顺序填入对应的值,咱们来为first_table
表插入第一行数据:
mysql> INSERT INTO first_table(first_column, second_column) VALUES(1, 'aaa');
Query OK, 1 row affected (0.00 sec)
mysql>
复制代码
这个语句的意思就是咱们要向first_table
表中插入一行数据,first_column
列的值是1
,second_column
列的值是'aaa'
。看一下如今表中的数据:
mysql> SELECT * FROM first_table;
+--------------+---------------+
| first_column | second_column |
+--------------+---------------+
| 1 | aaa |
+--------------+---------------+
1 row in set (0.00 sec)
mysql>
复制代码
第一行数据就插入成功了!
咱们也能够只指定部分的列,没有显式指定的列的值将被设置为NULL
,意思是尚未指定值,好比这样写:
mysql> INSERT INTO first_table(first_column) VALUES(2);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO first_table(second_column) VALUES('ccc');
Query OK, 1 row affected (0.00 sec)
mysql>
复制代码
第一条插入语句咱们只指定了first_column
列的值是2,而没有指定second_column
的值,因此second_column
的值就是NULL
;第二条插入语句咱们只指定了second_column
的值是'ccc'
,而没有指定first_column
的值,因此first_column
的值就是NULL
,也表示没有数据~ 看一下如今表中的数据:
mysql> SELECT * FROM first_table;
+--------------+---------------+
| first_column | second_column |
+--------------+---------------+
| 1 | aaa |
| 2 | NULL |
| NULL | ccc |
+--------------+---------------+
3 rows in set (0.00 sec)
mysql>
复制代码
每插入一行数据写一条语句也不是不行,可是对人来讲太烦了,并且每插入一行数据提交一个请求给服务器远没有一次把全部插入的数据提交给服务器效率高,因此MySQL
为咱们提供了批量插入的语句:
INSERT INTO 表名(列1,列2, ...) VAULES(列1的值,列2的值, ...), (列1的值,列2的值, ...), (列1的值,列2的值, ...), ...;
复制代码
也就是在原来的单条插入语句后边多写几项插入行的内容,用逗号分隔开就行了,举个例子:
mysql> INSERT INTO first_table(first_column, second_column) VALUES(4, 'ddd'), (5, 'eee'), (6, 'fff');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM first_table;
+--------------+---------------+
| first_column | second_column |
+--------------+---------------+
| 1 | aaa |
| 2 | NULL |
| NULL | ccc |
| 4 | ddd |
| 5 | eee |
| 6 | fff |
+--------------+---------------+
6 rows in set (0.01 sec)
mysql>
复制代码
能够看到3行记录就插入成功了!
若是一个表不用了,就能够删掉了,在真实环境中删除表必定要慎重谨慎,失去了的就再也回不来了~ 看一下删除的语法:
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
表,说明删除成功了!
若是咱们尝试删除某个不存在的表的话会报错:
mysql> DROP TABLE first_table;
ERROR 1051 (42S02): Unknown table 'xiaohaizi.first_table'
mysql>
复制代码
提示咱们要删除的表并不存在,若是想避免报错,可使用这种删除语法:
DROP TABLE IF EXISTS 表名;
复制代码
而后再删除一下不存在的first_table
表:
mysql> DROP TABLE IF EXISTS first_table;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql>
复制代码
这样就不报错了~
对于某些列来讲,可能有一些特殊含义或者用法,咱们把这些特殊的含义或用法称为列的属性
,也能够称为列的约束性条件
,在建立表的时候能够显式的定义出来。下边咱们看都有哪些约束性条件以及怎么在建立表的时候把它们定义出来。
前边介绍INSERT
语句的时候说过,若是在指定的插入列中省略了某些列,那这些列的值将被设置为NULL
,也就是列的默认值为NULL
,表示没有设置值。咱们在建立表的时候也能够指定一些有意义的默认值,指定方式以下:
列名 列的类型 DEFAULT 默认值
复制代码
好比咱们把first_table
的second_column
列的默认值指定为'abc'
,建立一下这个表:
mysql> CREATE TABLE first_table (
-> first_column INT,
-> second_column VARCHAR(100) DEFAULT 'abc'
-> );
Query OK, 0 rows affected (0.02 sec)
mysql>
复制代码
而后插入一条数据后看看默认值是否是起了做用:
mysql> INSERT INTO first_table(first_column) VALUES(1);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM first_table;
+--------------+---------------+
| first_column | second_column |
+--------------+---------------+
| 1 | abc |
+--------------+---------------+
1 row in set (0.00 sec)
mysql>
复制代码
咱们的插入语句并无指定second_column
的值,可是能够看到插入结果是按照咱们规定的默认值'abc'
来设置的。
若是咱们不设置默认值,其实就至关于指定的默认值为NULL
,好比first_table
表并无设置first_column
列的默认值,那它的默认值就是NULL
,也就是说上边的表定义语句和下边这个是等价的:
CREATE TABLE first_table (
first_column INT DEFAULT NULL,
second_column VARCHAR(100) DEFAULT 'abc'
);
复制代码
对于某些列,咱们要求它们是必填的,也就是不容许存放NULL
值,咱们用这样的语法来定义这个列:
列名 列的类型 NOT NULL
复制代码
好比咱们把first_table
的first_column
列定义为NOT NULL
。固然,咱们在从新定义表以前须要把原来的表删掉:
mysql> DROP TABLE first_table;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE first_table (
-> first_column INT NOT NULL,
-> second_column VARCHAR(100) DEFAULT 'abc'
-> );
Query OK, 0 rows affected (0.02 sec)
mysql>
复制代码
这样的话,咱们就不能再往这个字段里插入NULL
值了,好比这样:
mysql> INSERT INTO first_table(first_column, second_column) VALUES(NULL, 'aaa');
ERROR 1048 (23000): Column 'first_column' cannot be null
mysql>
复制代码
能够看到,弹出了错误提示。
一旦对某个列定义了NOT NULL
属性,那这个列的默认值就不为NULL
了。上边first_column
并无指定默认值,意味着咱们在使用INSERT
插入行时必须显式的指定这个列的值,而不能省略它,好比这样就会报错的:
mysql> INSERT INTO first_table(second_column) VALUES('aaa');
ERROR 1364 (HY000): Field 'first_column' doesn't have a default value mysql> 复制代码
能够看到执行结果提示咱们first_column
并无设置默认值,因此在插入数据的时候不能省略掉这个列的值。
有时候在咱们的表里能够经过某个列或者某些列肯定惟一的一条记录,咱们就能够把这个列或者这些列称为候选键
。好比在学生信息表student_info
中,只要咱们知道某个学生的学号,就能够肯定一个惟一的学生信息,也就是一条记录。固然,咱们也能够经过身份证号来肯定惟一的一条学生信息记录,因此学号
和身份证号
均可以做为学生信息表的候选键
。在学生成绩表student_score
中,咱们能够经过学号
和科目
这两个列的组合来肯定惟一的一条成绩记录,因此学号、科目
这两个列的组合能够做为学生成绩表的候选键
。
一个表可能有多个候选键,咱们能够选择一个候选键做为表的主键
。从定义中就能够看出,一个表最多只能有一个主键,主键的值不能重复,经过主键能够找到惟一的一条记录。若是咱们的表中有定义主键的需求能够选用下边这两种方式之一来指定主键:
若是主键只是单个列的话,能够直接在该列后声明PRIMARY KEY
,好比咱们把学生信息表student_info
的学号
列声明为主键能够这么写:
CREATE TABLE student_info (
number INT PRIMARY KEY,
name VARCHAR(5),
sex ENUM('男', '女'),
id_number CHAR(18),
department VARCHAR(30),
major VARCHAR(30),
enrollment_time DATE
);
复制代码
咱们也能够把主键的声明单独提取出来,用这样的形式声明:
PRIMARY KEY (列名1, 列名2, ...)
复制代码
而后把这个主键声明放到列定义的后边就行了。好比student_info
的学号
列声明为主键也能够这么写:
CREATE TABLE student_info (
number INT,
name VARCHAR(5),
sex ENUM('男', '女'),
id_number CHAR(18),
department VARCHAR(30),
major VARCHAR(30),
enrollment_time DATE,
PRIMARY KEY (number)
);
复制代码
值得注意的是,对于多个列的组合做为主键的状况,必须使用这种单独声明的形式,好比student_score
表里的学号,科目
的列组合做为主键,能够这么声明:
CREATE TABLE student_score (
number INT,
subject VARCHAR(30),
score TINYINT,
PRIMARY KEY (number, subject)
);
复制代码
在咱们建立表的时候就声明了主键的话,MySQL
会对咱们插入的记录作校验,若是两条记录里有相同的主键值的话就会报错。
另外,主键列默认是NOT NULL
的,也就是必填的,若是填入NULL
值会报错(先删除原来的student_info
表,使用上边的两种方式之一从新建立表):
mysql> INSERT INTO student_info(number) VALUES(NULL);
ERROR 1048 (23000): Column 'number' cannot be null
mysql>
复制代码
因此你们在插入数据的时候至少别忘了给主键列赋值哈~
对于不是主键的其余候选键,若是咱们也想让MySQL
替咱们校验数据的惟一性,那咱们能够把这个列或列组合声明为UNIQUE
的,代表该列或者列组合的值是不容许重复的,这种列的属性叫作惟一性约束
。同主键的定义同样,惟一性约束
的定义也有两种方式:
若是具备惟一性约束
的列是单个列的话,能够直接在该列后声明UNIQUE
或者UNIQUE KEY
,好比在学生信息表student_info
中,咱们不容许两条学生记录中的身份证号是同样的,那咱们让id_number
这一列具备惟一性约束。
CREATE TABLE student_info (
number INT PRIMARY KEY,
name VARCHAR(5),
sex ENUM('男', '女'),
id_number CHAR(18) UNIQUE,
department VARCHAR(30),
major VARCHAR(30),
enrollment_time DATE
);
复制代码
咱们也能够把惟一性约束的声明单独提取出来,用这样的形式声明:
UNIQUE [约束名称] (列名1, 列名2, ...)
复制代码
或者:
UNIQUE KEY [约束名称] (列名1, 列名2, ...)
复制代码
其中的约束名称
是可选的,其实就是咱们为这个惟一性约束起的一个名字而已,若是不起名字的话该名称默认和列名相同,这个不重要哈~ 而后把这个惟一性约束声明放到列定义的后边就行了。好比student_info
的身份证号
列声明惟一性约束的属性也能够这么写:
CREATE TABLE student_info (
number INT PRIMARY KEY,
name VARCHAR(5),
sex ENUM('男', '女'),
id_number CHAR(18),
department VARCHAR(30),
major VARCHAR(30),
enrollment_time DATE,
UNIQUE KEY (id_number)
);
复制代码
值得注意的是,对于多个列的组合具备惟一性约束的状况,必须使用这种单独声明的形式。
若是表中定义了惟一性约束的话,MySQL
会对咱们插入的记录作校验,若是插入的值违反了惟一性约束的话就会报错!
主键和惟一性约束都能保证某个列或者列组合的惟一性,可是:
小贴士: 你可能会问为啥主键列不容许存放NULL值,而普通的惟一性约束列却能够呢?哈哈,这涉及到底层存储的事情,如今你只须要记住这个规定就行了,若是你想知道更多的事情,那就继续日后看呗~
插入到学生成绩表student_score
中的学号(number
)列中的值必须能在学生基本信息表student_info
中的学号列中找到,不然若是一个学号只在成绩表里出现,而在信息表里找不到相应的记录的话,就至关于插入了一个不知道是哪一个学生的成绩,这显然是荒谬的。为了防止这样荒谬的状况出现,MySQL
给咱们提供了外键约束机制。定义外键的语法是这样的:
CONSTRAINT [外键名称] FOREIGN KEY(列1, 列2, ...) REFERENCES 父表名(父列1, 父列2, ...);
复制代码
其中的外键名称
也是可选的,一个名字而已有没有都行,不是很重要~ 若是A表中的某个列或者某些列依赖与B表中的某个列或者某些列,那么就称A表为子表
,B表为父表
。子表和父表可使用外键来关联起来,上边例子中student_info
就是一个父表,student_score
就是子表,咱们能够这样来定义student_score
列,来使用外键关联起父表和子表:
CREATE TABLE student_score (
number INT,
subject VARCHAR(30),
score TINYINT,
PRIMARY KEY (number, subject),
CONSTRAINT FOREIGN KEY(number) REFERENCES student_info(number)
);
复制代码
这样,在对student_score
表插入数据的时候,MySQL
都会为咱们检查一下插入的学号是否能在student_info
中找到,若是找不到则会报错。
小贴士: 父表中做为外键的列或者列组合必须创建索引,主键和具备惟一性约束的列默认的都创建了索引,置于什么是索引,咱们以后会详细唠叨的。
若是一个表中的某个列是数值类型的,包括整数类型和浮点数类型,那么这个列能够设置自增
属性。所谓自增,意思是若是咱们在插入数据的时候不指定该列的值,那么该列的值就是上一列的值加1后的值,定义语法就是这样:
列名 列的类型 AUTO_INCREMENT
复制代码
好比咱们想在first_table
里设置一个自增列id
,并把这个列设置为主键,来惟一标记一行记录,咱们能够这么写:
mysql> DROP TABLE first_table;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE first_table (
-> id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-> first_column INT,
-> second_column VARCHAR(100) DEFAULT 'abc'
-> );
Query OK, 0 rows affected (0.01 sec)
mysql>
复制代码
先把原来的表删掉,而后在新表中增长了一个非负int
类型的id
列,并把它设置为主键并且具备递增属性,那咱们插入数据的时候就能够不用管这个列,可是它的值将会递增,看:
mysql> INSERT INTO first_table(first_column, second_column) VALUES(1, 'aaa'), (2, 'bbb'), (3, 'ccc');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM first_table;
+----+--------------+---------------+
| id | first_column | second_column |
+----+--------------+---------------+
| 1 | 1 | aaa |
| 2 | 2 | bbb |
| 3 | 3 | ccc |
+----+--------------+---------------+
3 rows in set (0.00 sec)
mysql>
复制代码
能够看到,列id
是从1开始递增的。在使用递增属性的时候须要注意这几点:
AUTO_INCREMENT
属性的列必须创建索引。主键和具备惟一性约束的列会自动创建索引,至于什么是索引,咱们后边会详细唠叨。AUTO_INCREMENT
属性的列是从1开始递增的,因此最好用UNSIGNED
来修饰这个列,能够提高正数的表示范围。每一个列能够有多个约束性条件,声明的顺序无所谓,各个约束性条件之间用空白隔开就行了~
小贴士: 注意,有的约束性条件是冲突的,一个列不能具备两个冲突的约束性条件,好比一个列不能既声明为`PRIMARY KEY,又声明为UNIQUE KEY`,不能既声明为`DEFAULT NULL`,又声明为`NOT NULL`。你们在使用过程当中须要注意这一点。
咱们能够对每一个列信息以及表做注释,具体语法以下:
CREATE TABLE 表名 (
列1 列的类型 [列的属性] COMMENT '列1的注释信息',
列2 列的类型 [列的属性] COMMENT '列2的注释信息',
列3 列的类型 [列的属性] COMMENT '列3的注释信息',
) COMMENT '表的注释信息';
复制代码
好比咱们能够这样建立咱们的first_table
表:
CREATE TABLE first_table (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '自增主键',
first_column INT COMMENT '第一列',
second_column VARCHAR(100) DEFAULT 'abc' COMMENT '第二列'
) COMMENT '第一个表';
复制代码
注释不必太长,言简意赅便可,毕竟是给人看的,让人看明白是个啥意思就OK了。为了咱们本身的方便,也为了阅读你建立的人的方便,请遵照一下职业道德,写个注释吧~ 求求你了~ 求求你了~ 求求你了~
像数据库名、表名、列名、约束名称或者咱们以后会遇到的别的名称,这些咱们起的名字通通被称为标识符
。虽然MySQL
中对标识符
的命名没多少限制,可是却不欢迎下边的这几种命名:
名称中全都是数字。
由于在一些MySQL
命令中也会使用到数字,若是你起的名称中所有都是数字,会让MySQL
服务器分别不清哪一个是名称,哪一个是数字了。好比名称1234567
就是非法的。
名称中有空白字符
MySQL
命令是靠空白字符来分隔各个单词的,好比下边这两行命令是等价的:
CREATE DATABASE xiaohaizi;
CREATE DATABASE xiaohaizi;
复制代码
可是若是你定义的名称中有空白字符,这样会被看成两个词去处理,就会形成歧义。好比名称word1 word2 word3
就是非法的。
名称使用了MySQL
中的保留字
MySQL
中有不少保留的词是会被看成命令处理的,好比CREATE
、DATABASE
、DROP
、TABLE
等等等等,咱们稍后还会介绍大量的命令,这些命令用到的单词都是做为MySQL的保留字,若是你的名称用到了这些词儿也会致使歧义。好比名称create
就是非法的。
虽然某些名称可能会致使歧义,可是若是你坚持要使用的话,也不是不行,你可使用反引号``
来将你定义的名称扩起来,这样MySQL
的服务器就能检测到你提供的是一个名称而不是别的什么东西,好比说把上边几个非法的名称加上反引号``
就变成合法的名称了:
`1234567`
`word1 word2 word3`
`create`
复制代码
咱们上边对表first_table
的定义能够把里边的标识符全都使用反引号``
引发来,这样语义更清晰一点:
CREATE TABLE `first_table` (
`id` int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`first_column` INT,
`second_column` VARCHAR(100) DEFAULT 'abc'
);
复制代码
虽然反引号比较强大,可是咱们仍是建议你们不要起各类非主流的名称,也不要使用全数字、带有空白字符或者MySQL保留字的名称。因为MySQL是C语言实现的,因此在名称定义上仍是尽可能听从C语言的规范吧,就是用小写字母、数字、下划线、美圆符号等做为名称,若是有多个单词的话,各个单词之间用下划线链接起来,好比student
、student_info
啥的~
有时候咱们可能忘记了本身定义的表的结构,可使用下边这些语句来查看,它们起到的效果都是同样的:
DESCRIBE 表名;
DESC 表名;
EXPLAIN 表名;
SHOW COLUMNS FROM 表名;
SHOW FIELDS FROM 表名;
复制代码
好比咱们看一下student_info
这个表的结构:
mysql> DESC student_info;
+-----------------+-------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------------+------+-----+---------+-------+
| number | int(11) | NO | PRI | NULL | |
| name | varchar(5) | YES | | NULL | |
| sex | enum('男','女') | YES | | NULL | |
| id_number | char(18) | YES | UNI | 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
表的各个列的类型和属性就都展现出来了,其中PRI
是PRIMARY KEY
的缩写,UNI
是UNIQUE KEY
的缩写。
小贴士: 请注意`number`列的类型是`int(11)`,这个小括号里的`11`是什么意思?这个`11`实际上是所谓的显示宽度,咱们稍后立刻唠叨。
若是你看不惯这种详细展现各个字段的的信息,咱们还可使用下边这个语句来查看表结构:
SHOW CREATE TABLE 表名;
复制代码
好比:
mysql> SHOW CREATE TABLE student_info;
+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| student_info | CREATE TABLE `student_info` (
`number` int(11) NOT 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,
PRIMARY KEY (`number`),
UNIQUE KEY `id_number` (`id_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
复制代码
因为这行数据太长了,因此输出效果并非很好,因此把原来用于标记语句结束的分号;
改成\G
,这样的效果可能好点:
mysql> SHOW CREATE TABLE student_info\G
*************************** 1. row ***************************
Table: student_info
Create Table: CREATE TABLE `student_info` (
`number` int(11) NOT 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,
PRIMARY KEY (`number`),
UNIQUE KEY `id_number` (`id_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql>
复制代码
能够看到,使用SHOW CREATE TABLE
这种语句展现出来的表结构就是咱们平时建立表的语句。并且MySQL
默认为主键字段加了NOT NULL
属性,为其余字段加了DEFAULT NULL
属性,并且还给身份证号
的惟一性约束起了和列名同样的名称。
小贴士: 你可能疑惑的是在表定义末尾的`ENGINE=InnoDB DEFAULT CHARSET=utf8`是什么意思,这个是指定表的存储引擎和默认字符集,这些内容后边会有专门的专题来详细唠叨的,你如今不用关心~
对于无符号整数类型的列,咱们能够在查询数据的时候让数字左边补0,若是想实现这个效果须要给该列加一个ZEROFILL
属性,就像这样:
mysql> CREATE TABLE zero_table (
-> i1 INT UNSIGNED ZEROFILL,
-> i2 INT UNSIGNED
-> );
Query OK, 0 rows affected (0.03 sec)
mysql>
复制代码
咱们在zero_table
表中建立了两个整数列,不一样的是i1
列具备ZEROFILL
属性,下边咱们为这个表插入一条记录:
mysql> INSERT INTO zero_table(i1, i2) VALUES(1, 1);
Query OK, 1 row affected (0.00 sec)
mysql>
复制代码
而后咱们使用查询语句来显示一下刚插入的数据:
mysql> SELECT * FROM zero_table;
+------------+------+
| i1 | i2 |
+------------+------+
| 0000000001 | 1 |
+------------+------+
1 row in set (0.00 sec)
mysql>
复制代码
对于具备ZEROFILL
属性的i1
列,在显示的时候补了一堆0,仔细数数发现是9个0,而没有ZEROFILL
属性的i2
列,在显示的时候并无补0。为何i1
列会补9个0呢?咱们查看一下zero_table
的表结构:
mysql> DESC zero_table;
+-------+---------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------------+------+-----+---------+-------+
| i1 | int(10) unsigned zerofill | YES | | NULL | |
| i2 | int(10) unsigned | YES | | NULL | |
+-------+---------------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
mysql>
复制代码
能够看到,其实i1
和i2
列的类型INT
后边都加了一个(10)
,这个10
就是所谓的显示宽度
。显示宽度
是在查询语句显示的结果中,若是声明了 ZEROFILL 属性的整数列的实际值的位数小于显示宽度时,会在实际值的左侧补0,使补0的位数和实际值的位数相加正好等于显示宽度。咱们也能够本身指定显示宽度,比方说这样:
mysql> DROP TABLE zero_table;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE zero_table (
-> i1 INT(5) UNSIGNED ZEROFILL,
-> i2 INT UNSIGNED
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO zero_table(i1, i2) VALUES(1, 1);
Query OK, 1 row affected (0.01 sec)
mysql> SELECT * FROM zero_table;
+-------+------+
| i1 | i2 |
+-------+------+
| 00001 | 1 |
+-------+------+
1 row in set (0.00 sec)
mysql>
复制代码
新建立的表中,i1
字段的显示宽度是5,因此最后的显示结果中补了4个0。
在查询时,数据自动补0的条件有这几个:
UNSIGNED ZEROFILL
的属性在建立表的时候,若是声明了ZEROFILL
属性的列没有声明UNSIGNED
属性,那MySQL
会为该列自动生成UNSIGNED
属性。
也就是说若是咱们建立表语句是这样的:
CREATE TABLE zero_table (
i1 INT ZEROFILL,
i2 INT UNSIGNED
);
复制代码
MySQL
会自动帮咱们为i1
列加上UNSIGNED
属性,也就是这样:
CREATE TABLE zero_table (
i1 INT UNSIGNED ZEROFILL,
i2 INT UNSIGNED
);
复制代码
每一个整数类型都会有默认的显示宽度。
好比TINYINT
的默认显示宽度是4
,INT
的默认显示宽度是(11)
... 若是加了UNSIGNED
属性,则该类型的显示宽度减1,好比TINYINT UNSIGNED
的显示宽度是3
,INT UNSIGNED
的显示宽度是11
...
显示宽度并不会影响实际类型的实际存储空间。
也就是说INT(1)
和INT(10)
其实并无什么区别,比方说zero_table
表中i1
列的显示宽度是5,而数字12345678
的位数是8,它照样能够被填入i1
列中:
mysql> INSERT INTO zero_table(i1, i2) VALUES(12345678, 12345678);
Query OK, 1 row affected (0.01 sec)
复制代码
对于没有声明ZEROFILL
属性的列,显示宽度没有一毛钱卵用。
记住,只有在查询声明了ZEROFILL
属性的列时,显示宽度才会起做用,不然忽略显示宽度这个东西的存在。
只有列的实际值的位数小于显示宽度时才会补0,实际值的位数大于显示宽度时照原样输出。
比方说咱们刚刚把12345678
存到了i1
列里,在展现这个值时,并不会截短显示的数据,而是照原样输出:
mysql> SELECT * FROM zero_table;
+----------+----------+
| i1 | i2 |
+----------+----------+
| 00001 | 1 |
| 12345678 | 12345678 |
+----------+----------+
2 rows in set (0.00 sec)
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>
复制代码
其余地方若是使用到表名的话,须要显式指定这个表所属的数据库,指明方式是这样的:
数据库名.表名
复制代码
好比咱们须要查询first_table
表中的数据,能够这么写:
SELECT * FROM xiaohaizi.first_table;
复制代码
查看表结构:
SHOW CREATE TABLE xiaohaizi.first_table\G
复制代码
在其余不肯定当前数据库的状况下,使用到表的地方也都须要加上所属的数据库名,就不一一列举了。
在表建立好以后若是对表的结构不满意,好比想增长或者删除一列,想修改某一列的数据类型或者约束性条件,想对表名或者列名进行重命名,这些操做通通都算是修改表结构。MySQL
给咱们提供了一系列修改表结构的语句。
咱们能够经过下边这两种方式来修改表的名称:
方式一:
ALTER TABLE 旧表名 RENAME TO 新表名;
复制代码
咱们把first_table
表的名称修改成first_table1
:
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
表转移到这个数据库下:
mysql> ALTER TABLE xiaohaizi.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
里边了。咱们再换一种方式把它转回来,而且改名为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) DEFAULT '1234' COMMENT '第三列';
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC first_table;
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| first_column | int(11) | YES | | NULL | |
| second_column | varchar(100) | YES | | abc | |
| third_column | char(4) | YES | | 1234 | |
+---------------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql>
复制代码
经过查看表的结构能够看到该列已经添加成功了。
默认的状况下列都是加到现有列的最后一列,咱们也能够在添加列的时候指定它的位置,具体有两种方式:
添加到第一列:
ALTER TABLE 表名 ADD COLUMN 列名 列的类型 [列的属性] FIRST;
复制代码
让咱们把fourth_column
插入到第一列:
mysql> ALTER TABLE first_table ADD COLUMN fourth_column CHAR(4) DEFAULT '1234' COMMENT '第四列' FIRST;
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC first_table;
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| fourth_column | char(4) | YES | | 1234 | |
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| first_column | int(11) | YES | | NULL | |
| second_column | varchar(100) | YES | | abc | |
| third_column | char(4) | YES | | 1234 | |
+---------------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql>
复制代码
看到插入成功了。
添加到指定列的后边:
ALTER TABLE 表名 ADD COLUMN 列名 列的类型 [列的属性] AFTER 指定列名;
复制代码
再插入一个fifth_column
到first_column
后边瞅瞅:
mysql> ALTER TABLE first_table ADD COLUMN fifth_column CHAR(4) DEFAULT '1234' COMMENT '第五列' AFTER first_column;
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC first_table;
+---------------+------------------+------+-----+---------+----------------+
复制代码
| Field | Type | Null | Key | Default | Extra | +---------------+------------------+------+-----+---------+----------------+ | fourth_column | char(4) | YES | | 1234 | | | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | first_column | int(11) | YES | | NULL | | | fifth_column | char(4) | YES | | 1234 | | | second_column | varchar(100) | YES | | abc | | | third_column | char(4) | YES | | 1234 | | +---------------+------------------+------+-----+---------+----------------+ 6 rows 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: 0
mysql> ALTER TABLE first_table DROP COLUMN fourth_column;
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE first_table DROP COLUMN fifth_column;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC first_table;
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| first_column | int(11) | YES | | NULL | |
| second_column | varchar(100) | YES | | abc | |
+---------------+------------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql>
复制代码
能够看到删除成功了。
修改列的信息有下边这两种方式:
方式一:
ALTER TABLE 表名 MODIFY 列名 新数据类型 [新属性];
复制代码
咱们来修改一下first_table
表的second_column
列,把它修改成VARCHAR(2)
以及具备NOT NULL
约束条件:
mysql> ALTER TABLE first_table MODIFY second_column VARCHAR(2) NOT NULL COMMENT '第二列';
ERROR 1406 (22001): Data too long for column 'second_column' at row 1
mysql>
复制代码
咦,看到报了个错,意思是second_column
列里存放的数据太大了,咱们看看都存了哪些数据:
mysql> SELECT * FROM first_table;
+----+--------------+---------------+
| id | first_column | second_column |
+----+--------------+---------------+
| 1 | 1 | aaa |
| 2 | 2 | bbb |
| 3 | 3 | ccc |
+----+--------------+---------------+
3 rows in set (0.00 sec)
mysql>
复制代码
原来存放的数据是'aaa'
、'bbb'
和'ccc'
,它们都是包含3个字符的字符串。如今咱们要把second_column
列的数据类型改成VARCHAR(2)
,而VARCHAR(2)
最多只能存放两个字符,因此才会报错了!知道了错误缘由后,咱们把类型改成VARCHAR(3)
试试:
mysql> ALTER TABLE first_table MODIFY second_column VARCHAR(3) NOT NULL COMMENT '第二列';
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> DESC first_table;
+---------------+------------------+------+-----+---------+----------------+
复制代码
| Field | Type | Null | Key | Default | Extra | +---------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | first_column | int(11) | YES | | NULL | | | second_column | varchar(3) | NO | | NULL | | +---------------+------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
mysql>
```
好了,这回就对了。这个过程也提醒咱们:<span style="color:red">不能随便修改列信息,修改后的数据类型和属性必定要兼容表中现有的数据!</span>。
复制代码
方式二:
ALTER TABLE 表名 CHANGE 旧列名 新列名 新数据类型 [新属性];
复制代码
能够看到这种修改方式须要咱们填两个列名,也就是说在修改数据类型和属性的同时也能够修改列名!好比咱们修改second_column
的列名为second_column1
:
mysql> ALTER TABLE first_table CHANGE second_column second_column1 VARCHAR(3) NOT NULL COMMENT '第二列';
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC first_table;
+----------------+------------------+------+-----+---------+----------------+
复制代码
| Field | Type | Null | Key | Default | Extra | +----------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | first_column | int(11) | YES | | NULL | | | second_column1 | varchar(3) | NO | | NULL | | +----------------+------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
mysql>
```
咱们只是把`second_column`的列名修改了一下而已,并无改动它的数据类型和属性,因此直接把旧的数据类型和属性抄过来就行了,能够看到结果名称已经被修改了。
复制代码
若是咱们以为当前列的顺序有问题的话,可使用下边这几条语句进行修改:
将列设为表的第一列:
ALTER TABLE 表名 MODIFY 列名 列的类型 列的属性 FIRST;
复制代码
先看一下如今表first_table
的各个列的排列顺序:
mysql> DESC first_table;
+----------------+------------------+------+-----+---------+----------------+
复制代码
| Field | Type | Null | Key | Default | Extra | +----------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | first_column | int(11) | YES | | NULL | | | second_column1 | varchar(3) | NO | | NULL | | +----------------+------------------+------+-----+---------+----------------+ 3 rows in set (0.01 sec)
mysql>
```
能够看到,列的顺序依次是: `id`、`first_column`、`second_column1`。如今咱们想把`first_column`放在第一列能够这么写:
```
mysql> ALTER TABLE first_table MODIFY first_column int(11) COMMENT '第一列' FIRST;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC first_table;
+----------------+------------------+------+-----+---------+----------------+
复制代码
| Field | Type | Null | Key | Default | Extra | +----------------+------------------+------+-----+---------+----------------+ | first_column | int(11) | YES | | NULL | | | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | second_column1 | varchar(3) | NO | | NULL | | +----------------+------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
mysql>
```
看到`first_column`已经成为第一列了!
复制代码
将列放到指定列的后边:
ALTER TABLE 表名 MODIFY 列名 列的类型 列的属性 after 指定列名;
复制代码
比方说咱们想把first_column
放到second_column1
后边能够这么写:
mysql> ALTER TABLE first_table MODIFY first_column int(11) COMMENT '第一列' AFTER second_column1;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC first_table;
+----------------+------------------+------+-----+---------+----------------+
复制代码
| Field | Type | Null | Key | Default | Extra | +----------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | second_column1 | varchar(3) | NO | | NULL | | | first_column | int(11) | YES | | NULL | | +----------------+------------------+------+-----+---------+----------------+ 3 rows 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;
复制代码
这样人敲的命令也少了,服务器也不用分屡次执行效率也高了,何乐而不为呢?
MySQL服务器
能够包含若干数据库,每一个数据库中能够包含若干个表。
数据库相关操做以下:
SHOW DATABASES;
CREATE DATABASE 数据库名;
USE 数据库名
DROP DATABASE 数据库名
表结构的相关操做以下:
建立表:
CREATE TABLE 表名 (
列名, 列的类型, [列的属性] COMMENT '列的注释',
... (若干个列的信息)
) COMMENT '表的注释';
复制代码
删除表:DROP TABLE 表名;
修改表:
修改表名:
方式一:
ALTER TABLE 旧表名 RENAME TO 新表名;
复制代码
方式二:
RENAME TABLE 旧表名1 TO 新表名1, 旧表名2 TO 新表名2, ... 旧表名n TO 新表名n;
复制代码
添加列:
ALTER TABLE 表名 ADD COLUMN 列名 列的类型 [列的属性] [FIRST|AFTER 指定列名];
复制代码
删除列:
ALTER TABLE DROP COLUMN 列名;
复制代码
修改列信息:
方式一:
ALTER TABLE 表名 MODIFY 列名 新数据类型 [新属性] [FIRST|AFTER 指定列名];
复制代码
方式二:
ALTER TABLE 表名 CHANGE 旧列名 新列名 新数据类型 [新属性] [FIRST|AFTER 指定列名];
复制代码
各类约束性条件
默认值:在插入语句中没有指定该列的值的状况下,使用默认值,声明语法以下:
列名 列的类型 DEFAULT 默认值
复制代码
非空约束:声明了该属性的列不容许插入NULL
值,声明语法:
列名 列的类型 NOT NULL
复制代码
主键:惟一标识一条记录,而且一个表中最多字能有一个主键,主键值不能为NULL
,声明语法:
方式一:
列名 列的类型 PRIMARY KEY
复制代码
方式二:
PRIMARY KEY (列名1, 列名2, ...)
复制代码
惟一性约束:惟一标识一条记录,一个表中能够有多个惟一性约束,而且值能够为NULL
,声明语法:
方式一:
列名 列的类型 UNIQUE [KEY]
复制代码
方式二:
UNIQUE [KEY] [约束名称] (列名1, 列名2, ...)
复制代码
外键:表A的某个列或列组合的值依赖表B的某个列或列组合的值,则成表A为子表,表B为父表,表A的该列或者列组合称为外键,声明外键的方式以下:
CONSTRAINT [外键名称] FOREIGN KEY(列1, 列2, ...) REFERENCES 父表名(父列1, 父列2, ...);
复制代码
自增:在插入语句没有包含自增列的状况下,该列的值会递增,声明方式以下:
列名 列的类型 AUTO_INCREMENT
复制代码
本系列专栏都是MySQL入门知识,想看进阶知识能够到小册中查看:《MySQL是怎样运行的:从根儿上理解MySQL》的连接 。小册的内容主要是从小白的角度出发,用比较通俗的语言讲解关于MySQL进阶的一些核心概念,好比记录、索引、页面、表空间、查询优化、事务和锁等,总共的字数大约是三四十万字,配有上百幅原创插图。主要是想下降普通程序员学习MySQL进阶的难度,让学习曲线更平滑一点~