MySQL数据库程序设计(二)

前言

SQLStructured Query Language),被称为结构化查询语言,是目前主流的关系型数据库上执行数据操作、数据检索以及数据库维护所需要的标准语言。它将数据查询、数据操纵、事务控制、数据定义和数据控制集于一身。不分大小写,习惯上,关键字用大写,表名列命用小写。

MySQL编程语言

MySQL数据库服务器的交互实质,都是通过结构化查询语言来实现的,所以SQL是各类数据库交互方式的基础。

结构化查询语言SQL

SQL是机构化查询语言(Structured Query Language)的英文首字母,专门用来与数据库通信的语言。SQL由很多关键字组成。SQL具有以下优点:

  • 只要关系数据库都支持SQL,而非专有语言
  • SQL简单易学。单词描述性很强,单词数量不多
  • SQL虽然很简单,但确是一种强有力的语言,灵活使用可以进行复杂和高级的数据库操作

MySQL语言组成

MySQL数据库所支持的SQL语言包含:数据库定义语言(DDL)、数据库操纵语言(DML)、数据库控制语言(DCL)。

数据库定义语言(DDL)

主要用于对数据库的对象进行创建、删除、修改等操作。数据库对象包括:表、默认约束、规则、试图、触发器、存储过程等。主要SQL语句为:

  • CREATE:用于创建数据库或数据库对象。
  • ALTER:用于对数据库或数据库对象的修改。
  • DROP:用于对数据库或数据库对象的删除。

数据操纵语言(DML)

主要对数据库对象的数据进行查询、增加、删除、修改等操作。主要SQL语句为:

  • SELECT:用于表或视图的数据查询
  • INSERT:将数据插入表或视图中。
  • UPDATE:修改表或视图的数据,可以修改一条,多条、全部数据。
  • DELETE:删除表或视图的数据,一定要加条件否则会删除全部数据。

数据控制语言(DCL)

用于安全管理,例如显示数据库登录用户权限。主要SQL语句为:

  • GRANT:用于授予权限,可以把操纵语言指定权限分配给用户。
  • REVOKE:用于收回授予的权限,不会对数据库有影响。

MySQL扩展增加的语言要素

主要包括一些常用的常量、变量、运算符、表达式、函数、流程控制和注解等。
(1)常量
在程序运行过程中值不变的量。

  • 字符串常量:单引号或双引号括起来的字符序列,分为ASCII字符串常量和Unicode字符串常量
  • 数值常量:可分为整数和浮点数常量,其中整数不带小数点,浮动带小数点。
  • 十六进制常量:一个十六进制值通常指定为一个字符串常量,每对十六进制数字被转换为一个字符。
  • 日期时间常量:用单引号将表示日期时间的字符串。
  • 位字段值:使用b’value’,value是一个0或1的二进制值。
  • 布尔值:TRUEFALSETRUE的数字值是1,FALSE的数字值是0。
  • NULL值:表示没有值。
    (2)变量
    变量用于临时存量数据,变量有名字和数据类型两个属性,名字用了标识变量,数据可随程序运行变化。
    在MySQL中分为用户变量和系统变量。在使用用户变量时添加一个“@”符号,用于将其与列名分开。
    (3)运算符
  • 常用的运算符:算术运算符、位运算符、比较运算符、逻辑运算符。
  • 算术运算符:+(加)、-(减)、*(乘)、/(除)、%(取余)。
  • 位运算符:&(与)、|(或)、^(异或)、~(取反)、>>(右移)、<<(左移)。
  • 比较运算符:=(等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)、<>(不等于)、!=(不等于)、<=>(相等或等于空)。
  • 逻辑运算符:NOT或!(非)、AND或&&(与)、OR或||(或)、XOR(异或)。
    (4)表达式
    表达式是常量、变量、列名、复杂计算、运算符和函数的组合。一个表达式可以得到一个值,表达式也有数据类型。
    (5)内置函数
    通常可以调用系统提供的内置函数来对数据库表进行相关操纵。下面举例几个常用的:
  • 数学函数:ABS()函数、SORT()函数。
  • 聚合函数:COUNT()函数。
  • 字符串函数:ASCII()函数、CHAR()函数。
  • 日期和时间函数:NOW()函数、YEAR()函数。
  • 控制流程函数:IF()函数、IFNULL()函数

MySQL函数

MySQL提供的内置函数,可以帮助用户更加方便的处理表的数据。

聚合函数

根据一组数据求出一个值。聚合函数的结果只对非NULL的值进行计算,NULL则被忽略,以下面数据为例,介绍几个常用的聚合函数。

mysql> select * from tb_student;
+------------+--------------+------+----------+
| student_no | student_name | age  | class_no |
+------------+--------------+------+----------+
|          1 | 张三         |   17 | 001      |
|          2 | 李四         |   18 | 001      |
|          3 | 王五         |   17 | 001      |
|          4 | 小六         |   19 | 002      |
+------------+--------------+------+----------+
4 rows in set (0.02 sec)

(1)COUNT()函数:查询表中所有行数。

mysql> select count(*) from tb_student;
+----------+
| count(*) |
+----------+
|        4 |
+----------+
1 row in set (0.00 sec)

(2)SUM()函数:计算某个字段的总和。

mysql> select sum(age) from tb_student;
+----------+
| sum(age) |
+----------+
|       71 |
+----------+
1 row in set (0.00 sec)

(3)AVG()函数:计算某个字段平均值。

mysql> select avg(age) from tb_student;
+----------+
| avg(age) |
+----------+
|  17.7500 |
+----------+
1 row in set (0.00 sec)

(4)MAX()函数:找到某个字段的最大值。

mysql> select max(age) from tb_student;
+----------+
| max(age) |
+----------+
|       19 |
+----------+
1 row in set (0.00 sec)

(5)MIN()函数:找到某个字段的最小值。

mysql> select min(age) from tb_student;
+----------+
| min(age) |
+----------+
|       17 |
+----------+
1 row in set (0.00 sec)

数学函数

主要用于处理数字类型。
(1)ABS()函数:计算某个字段的绝对值。

mysql> select abs(1),abs(-1);
+--------+---------+
| abs(1) | abs(-1) |
+--------+---------+
|      1 |       1 |
+--------+---------+
1 row in set (0.00 sec)

(2)FLOOR()函数:返回小于或等于参数的最大整数。

mysql> select floor(1.5),floor(-2);
+------------+-----------+
| floor(1.5) | floor(-2) |
+------------+-----------+
|          1 |        -2 |
+------------+-----------+
1 row in set (0.00 sec)

(3)RAND()函数:返回0-1之间的随机数

mysql> select rand(),rand();
+--------------------+--------------------+
| rand()             | rand()             |
+--------------------+--------------------+
| 0.8018397919850795 | 0.6479518717601447 |
+--------------------+--------------------+
1 row in set (0.00 sec)

(4)TRUNCATE()函数:保留小数点后几位值。

mysql> select truncate(1.23242,3);
+---------------------+
| truncate(1.23242,3) |
+---------------------+
|               1.232 |
+---------------------+
1 row in set (0.00 sec)

字符串函数

主要处理字符串类型。

(1)UPPER()和UCASE()函数:将字母转化为大写或小写。

mysql> select upper('abc'),ucase('ABC');
+--------------+--------------+
| upper('abc') | ucase('ABC') |
+--------------+--------------+
| ABC          | ABC          |
+--------------+--------------+
1 row in set (0.00 sec)

(2)LEFT()函数:返回字符串前n个字符。

mysql> select left('ABC',2);
+---------------+
| left('ABC',2) |
+---------------+
| AB            |
+---------------+
1 row in set (0.00 sec)

(3)SUBSTRING()函数:截取n到m长度的字符。

mysql> select substring('ABC',1,2);
+----------------------+
| substring('ABC',1,2) |
+----------------------+
| AB                   |
+----------------------+
1 row in set (0.00 sec)

日期和时间函数

(1)CURDATE()函数:返回当前日期。

mysql> select curdate();
+------------+
| curdate()  |
+------------+
| 2021-09-10 |
+------------+
1 row in set (0.00 sec)

(2)CURTIME()函数:返回当前时间。

mysql> select curtime();
+-----------+
| curtime() |
+-----------+
| 23:40:52  |
+-----------+
1 row in set (0.00 sec)

(3)NOW()函数:返回当前时间和日期。

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2021-09-10 23:40:59 |
+---------------------+
1 row in set (0.00 sec)

其他函数

除了上述介绍的,还有很多函数,例如条件判断函数等。

(1)IF()函数:判断表达式是否成立,返回对应结果。

mysql> select if(1>2,'大于','小于');
+-----------------------+
| if(1>2,'大于','小于') |
+-----------------------+
| 小于                  |
+-----------------------+
1 row in set (0.00 sec)

(2)IFNULL()函数:判断数据是否为空(NULL)。

mysql> select ifnull(null,'空');
+-------------------+
| ifnull(null,'空') |
+-------------------+
||
+-------------------+
1 row in set (0.00 sec)

数据定义

数据库可以看作是一个专门存储数据对象的容器,下面主要讲解使用SQL语句创建和操作数据库和表。

定义数据库

安装好MySQL(自行百度安装MySQL)后,就可以开始创建和使用数据库了,涉及数据库的创建、选择、查看、修改和删除操纵。

创建数据库

创建数据库是在系统磁盘上划分一块区域用于数据存储和管理,MySQL创建数据库的基本语法格式是:

CREATE {
   
   DATABASE | SCHEMA} [IF NOT EXISTS] 数据库名
[[DEFAULT] CHARACTER SET [=] 字符集名]
[[DEFAULT] COLLATE [=] 校对规则];

语法说明:

  • 语句中“[ ]”为可选项。
  • 语句中“|”为选择项,任选其一来组成SQL语句命令,“或”的关系。
  • IF NOT EXISTS:表示在创建数据库之前先判断,在不存在数据库的情况下在进行创建操纵,避免重复创建导致错误。
  • CHARACTER SET:指定数据库字符集,避免出现乱码情况,比如gb2312、utf-8。
  • COLLATE :指定字符校对规则,比如:gb2312_chinese_ci。

例子:在MySQL中创建一个db_class的数据库:

CREATE DATABASE IF NOT EXISTS db_class
DEFAULT CHARACTER SET GB2312
DEFAULT COLLATE GB2312_chinese_ci;

执行结果如下所示:

mysql> CREATE DATABASE IF NOT EXISTS school
    -> DEFAULT CHARACTER SET GB2312
    -> DEFAULT COLLATE GB2312_chinese_ci;
Query OK, 1 row affected (0.01 sec)

或者最简单的创建方式

CREATE DATABASE IF NOT EXISTS db_class;

用户创建数据库需要获得相对应的权限,上述命令执行成功后会在MySQL的data目录下创建一个与数据库名称相同的文件夹。

选择与查看数据库

在实际开发过程用会有多个数据库的情况,下面介绍如何快速的查看和选择数据库。

  1. 查看数据库
    当数据很多的时候往往会忘记有多少个数据库,甚至记不太清楚正确的数据库名是什么。

语法格式:

SHOW {
   
   DATABASES | SCHEMAS};

执行结果如下所示:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| school             |
+--------------------+
7 rows in set (0.00 sec)

可以看到,数据库不仅仅有我们创建的数据库,还包含系统自动创建的数据库,各个数据库的作用如下表所示。

数据库名称 数据库作用
mysql 配置用户访问权限
information_schema 保存MySQL服务器所维护的其他数据库信息,如数据库名、数据库的表、表的数据类型与访问权限等
performance_schema 收集数据库服务器性能参数
school 自定义数据库,用于学校系统管理
  1. 选择数据库

通过命令查看有哪些数据库了,可以通过命令跳转到指定数据库,才可以对数据库及表、数据进行各种操作。语法格式:

USE 数据库名;

执行结果如下所示:

mysql> use school;
Database changed

修改数据库

MySQL数据库的默认字符集为 latin1,默认校对规则为 latin1_swedish_ci,可以使用对应的语法对其修改。

ALTER {
   
   DATABASE | SCHEMA} 数据库名
[DEFAULT] CHARACTER SET [=] 字符集
[DEFAULT] COLLATE [=] 校对规则;

比如现在修改school数据库的字符集,执行结果如下所示:

mysql> alter database school
    -> default character set =gb2312
    -> default collate gb2312_chinese_ci;
Query OK, 1 row affected (0.00 sec)

删除数据库

删除数据库就是将创建好的数据库文件从磁盘上清除同时数据也会删除。语法格式:

DROP {
   
   DATABASE | SCHEMA} [IF EXISTS] 数据库名;

比如现在将school数据库删除,执行结果如下所示:

mysql> drop database school;
Query OK, 1 row affected (0.03 sec)

使用show databases;查看数据库,已经没有school的数据库了,如下所示:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

切忌误删系统自带的数据库,否则将不能正常运行。

定义表

数据库创建成功后,就可以在数据库中创建表了。表是数据库中最重要、最基本的数据对象,若没有表,数据库其他的数据对象就没有意义。表是按照行和列的格式来存储的,每一行代表一个记录,每一列代表记录的一个字段取值。创建表的过程就是定义每个字段的过程,也是实施数据完整性约束的过程。

MySQL常用数据类型

数据类型是指系统中所允许数据存储的类型。例如存放金额的字段应该用数值型,存放文本、人名等信息应该用字符型等。创建表时必须为表的每个字段指定正确的数据类型及可能的数据长度。数据类型不仅可以对数据进行排序,对优化方面也有重要作用。
MySQL常用的数据类型有数值类型、日期和时间、字符串类型,下面介绍常用的几种类型。

  1. 数值类型
数值类型 范围(有符号) 范围(无符号) 备注
BIT 1~64 1~64 位字段类型,默认长度为1
TINYINT -128~127 0~255 很小的整数
BOOL、BOOLEAN - - 等同于TINYINT(1)。true为真,false为假
INT、INTEGER -2147483648~2147483647 0~4294967295 普通大小的整数
DOUBLE -1.7976931348623157E+308-2.2250738585072014E-308),0,(2.2250738585072014E-3081.7976931348623157E+308 0~(2.2250738585072014E-308,1.7976931348623157E+308) 双精度浮点数值
DECIMAL - - 小数值,DECIMAL(M,D) ,如果M>D,为M+2否则为D+2
  1. 日期和时间类型
数值类型 范围 备注
DATE 1000-01-01~9999-12-31 日期型,格式为“YYYY-MM-DD”
TIME -838:59:59~838:59:59 时间型,格式为“HH:mm:ss”
DATETIME 1000-01-01 00:00:00~9999-12-31 23:59:59 日期时间型,格式为“YYYY-MM-DD HH:mm:ss”
YEAR 两位格式 :70~69表示1970 ~2069,四位格式:1901 ~ 2155 年,2位或3位,格式为“YYYY-MM-DD”
TIMESTAMP 1970-01-01 00:00:00~2037 时间戳,时间的秒数
  1. 字符串类型
数值类型 范围 备注
CHAR 0~255 固定长度的字符类型,不满足长度字符用空格代替
VARCHAR 0~65535 可变长度字符,存放多少字符就是多少字符
TINYTEXT 255(2^8-1) 短文本数据
TEXT 65535(2^16-1) 长文本数据

创建表

创建表使用 CREATE TABLE 语句,其基本语法格式为:

CREATE TABLE 表名(
字段名 数据类型 [列级完整性约束条件] [默认值],
... ...
)ENGINE = 引擎类型;

在已有school数据库中创建tb_student,并使用InnoDB引擎存储数据。如下所示:

mysql> create table tb_student(
    -> student_no int not null primary key auto_increment,
    -> student_name varchar(20) not null,
    -> age int not null,
    -> class_no varchar(10) default null
    -> )engine=Innodb;
Query OK, 0 rows affected (0.02 sec)

下面对上述语句进行说明:

  1. 指定表名和字段名
    创建表时,先选定当前数据库,必须指定表名,如“tb_student”。创建者必须拥有CREATE权限,多个字段通过逗号(,)分隔,字段名在表里唯一。
  2. 完整性约束条件
    创建表示也可以定义该表有关的完整性约束条件。包括实体完整性约束(PRIMARY KEYUNIQUE)、参数完整性约束(FOREIGN KEY)、用户自定义约束(NOT NULLDEFAULTCHECK约束等)。
  3. NULL和NOT NULL
    关键字NULLNOT NULL可以给字段自定义约束,NULL表示非必填项可以为NULLNOT NULL表示必填项,不允许为NULL。需注意NULL和空格之间的区别,空格(’ ‘)是一个有效字符串,NULL是一个关键字和空值(’’)。
  4. AUTO_INCREMENT
    AUTO_INCREMENT可以将字段设置为自增唯一值,只有整型才能设置,初始值为1,累计递增+1。
  5. DEFAULT
    DEFAULT表示字段的默认值,当没有值时默认使用设定好的参数。
  6. 存储引擎类型
    存储引擎是MySQL的核心,关系到如何存储数据、建立索引、更新、查询等技术的实现方法,用户可以根据不同需求选择不同存储引擎。
    可以使用SHOW ENGINES查看数据库支持的引擎:
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+

查看表

创建表后,可以通过命令查看某数据库创建的有哪些表及表的结构,确定表定义是否正确。

  1. 查看表的名称

语法格式如下:

SHOW TABLES;

执行如下所示:

mysql> use school;
Database changed
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| tb_student       |
+------------------+
1 row in set (0.00 sec)
  1. 查看表结构
    在MySQL中,可以使用DESCRIBE/DESC语句或SHOW CLUMNS查看表的结构,包括字段名、数据类型、默认值等。

语法格式如下:

SHOW COLUMNS FROM 表名;
DESC 表名;

执行如下所示:

mysql> show columns from tb_student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| age          | int         | NO   |     | NULL    |                |
| class_no     | varchar(10) | YES  |     | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> desc tb_student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| age          | int         | NO   |     | NULL    |                |
| class_no     | varchar(10) | YES  |     | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

当然,还可以查看表的详细结构,格式如下:

SHOW CREATE TABLE 表名;

执行如下所示:

mysql> show create table tb_student;
+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                                                                                    |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tb_student | CREATE TABLE `tb_student` (
  `student_no` int NOT NULL AUTO_INCREMENT,
  `student_name` varchar(20) NOT NULL,
  `age` int NOT NULL,
  `class_no` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`student_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

这样不仅可以查看创建表的详细语句,还可以查看存储引擎和字符编码。

修改表

有时候可能把表创建好了,应需求变动,需要对表做一些调整与修改。

  1. 添加字段

格式如下:

ALTER TABLE 表名 ADD COLUMN 字段名 数据类型 约束条件 [FIRST | AFTER];

[FIRST | AFTER]:表示新增字段的位置,是第一个字段还是在已有字段后面,默认最后一列。

比如:在tb_student表中新增id_no字段,执行如下所示:

mysql> alter table tb_student add column id_no varchar(32) not null unique ;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> desc tb_student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| age          | int         | NO   |     | NULL    |                |
| class_no     | varchar(10) | YES  |     | NULL    |                |
| id_no        | varchar(32) | NO   | UNI | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
  1. 修改字段

ALTER TABLE提供了三个修改字段的子句,分别如下:

(1)CHANGE子句。可以修改列名、数据类型,同时添加多个CHANGE子句只需逗号分开。

ALTER TABLE 表名 CHANGE [COLUMN]原字段名 新字段名 数据类型[约束条件];

比如:修改tb_student表的age字段改为student_age类型为bigint,默认值为0,执行如下所示:

mysql> alter table tb_student change column age student_age bigint(20) default 0;
Query OK, 0 rows affected, 1 warning (0.06 sec)
Records: 0  Duplicates: 0  Warnings: 1

mysql> desc tb_student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| student_age  | bigint      | YES  |     | 0       |                |
| class_no     | varchar(10) | YES  |     | NULL    |                |
| id_no        | varchar(32) | NO   | UNI | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

(2)ALTER子句。修改和删除列的默认值。

ALTER TABLE 表名 ALTER [COLUMN]字段名 {
   
   SET|DROP} DEFAULT;

比如:将student_no字段改为18,再删除默认值,执行如下所示:

mysql> alter table tb_student alter column student_age set default '18';
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc tb_student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| student_age  | bigint      | YES  |     | 18      |                |
| class_no     | varchar(10) | YES  |     | NULL    |                |
| id_no        | varchar(32) | NO   | UNI | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

mysql> alter table tb_student alter column student_age drop default;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc tb_student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| student_age  | bigint      | YES  |     | NULL    |                |
| class_no     | varchar(10) | YES  |     | NULL    |                |
| id_no        | varchar(32) | NO   | UNI | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

(3)MODIFY子句。与CHANGE子句不同,只能修改数据类型和列的顺序。

ALTER TABLE 表名 MODIFY [COLUMN]字段名 数据类型[约束条件][FIRST | AFTER];

比如:修改id_no的数据类型长度为int类型,排在class_no前面。

mysql> alter table tb_student modify column id_no int(18) after student_age;
Query OK, 0 rows affected, 1 warning (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 1

mysql> desc tb_student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| student_age  | bigint      | YES  |     | NULL    |                |
| id_no        | int         | YES  | UNI | NULL    |                |
| class_no     | varchar(10) | YES  |     | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
  1. 删除字段
    表的字段越多,DBMS的工作负荷会越大,所占空间也会增加。再优化数据库的时候会设计到一些字段的删除,一旦删除列,此列的内容也会删除。

语法格式为:

ALTER TABLE 表名 DROP [COLUMN]字段名;

比如:现在的班级号我想提取出来,单独新建一个表,此时需要删除此字段,执行如下所示:

mysql> alter table tb_student drop column class_no;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc tb_student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| student_age  | bigint      | YES  |     | NULL    |                |
| id_no        | int         | YES  | UNI | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

重命名表

有时候可能再新建表的时候把表名命名错了,需要重新命名,语法格式为:

ALTER TABLE 表名 RENAME [TO] 新表名;

或者

RENAME TABLE 表名 TO 新表名;

现在我们将tb_student改为student,方便输入,执行如下所示:

mysql> alter table tb_student rename to student;
Query OK, 0 rows affected (0.01 sec)

mysql> rename table tb_student to student;
Query OK, 0 rows affected (0.03 sec)

mysql> desc tb_student;
ERROR 1146 (42S02): Table 'school.tb_student' doesn't exist

mysql> desc student;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| student_no   | int         | NO   | PRI | NULL    | auto_increment |
| student_name | varchar(20) | NO   |     | NULL    |                |
| student_age  | bigint      | YES  |     | NULL    |                |
| id_no        | int         | YES  | UNI | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

再使用原来的表名就会报表不存在,所有操作都有用新的表名

删除表

当数据库重构以后,会有很多废弃的表,防止占用空间,浪费资源,需要将它删除,语法格式为:

DROP TABLE [IF EXISTS] 表名,....[表n];

加上IF EXISTS语句防止删除表时报错,删除多个表用逗号(,)隔开,比如:现在我要删除class_student表,执行如下所示:

mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| class_student    |
| student          |
+------------------+
2 rows in set (0.00 sec)

mysql> drop table class_student;
Query OK, 0 rows affected (0.01 sec)

mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| student          |
+------------------+
1 row in set (0.00 sec)

所有的表的删除操作都会影响对应的数据,所以删除需谨慎。

数据的完整性约束

关系模型的完整性规则是对关系的某种约束。保证数据的正确性和一致性,关系模型中有三类完整性约束,分别是实体完整性、参照完整性、用户定义的完整性。完整性约束能有效地防止对MySQL的意外破坏和非法存取,提高完整性检测的效率,减轻开发人员负担。

实体完整性

实体完整性是指关系的主属性不能为空值。

  1. 主键约束
    主键是表中某一列或某些列所构成的组合。再MySQL中,主键必须遵循如下规则:
    (1) 每个表只能定义一个主键。
    (2) 主键的值唯一且不能为NULL
    (3) 复合主键不能包含不必要的多余列。也就是说复合主键删除一列后,剩下的列仍满足唯一性原则,那么这个复合主键是不正确的,这是最小化原则。
    (4) 列名唯一。

主键约束使用PRIMARY KEY来实现,可以通过创建表或修改表示添加,其方式有两种,下面以新建一个class表来说明两种的区别:

  • 列级完整性约束,再字段后面添加关键字。
mysql> create table class(
    -> class_no int primary key,
    -> class_count int null,
    -> class_tech_no int not null
    -> )engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)
  • 表级完整性约束,再表的最后面添加关键字。
mysql> drop table class;
Query OK, 0 rows affected (0.01 sec)

mysql> create table class(
    -> class_no int,
    -> class_count int null,
    -> class_tech_no int not null,
    -> primary key(class_no)
    -> )engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)
  1. 完整性约束的命名
    与数据库的表和视图一样,可以对完整性约束进行添加、删除和修改等操作。语法格式为:
CONSTRAINT<约束名>
{
PRIMARY KEY(主键字段)
|UNIQUE(候选键字段)
|FOREIGN KEY(外键字段) REFERENCES 参照表(主键字段)
|CHECK(约束条件表达式)
};

比如:给班级表的class_teacher_no创建一个约束名为PK_tech的约束

mysql> drop table class;
Query OK, 0 rows affected (0.01 sec)

mysql> create table class(
    -> class_no int primary key,
    -> class_count int null,
    -> class_tech_no int not null,
    -> constraint PK_tech foreign key(class_tech_no) references tb_tech(tech_no)
    -> )engine=InnoDB;
Query OK, 0 rows affected (0.04 sec)
  1. 候选键约束
    候选键与主键一样,值必须唯一,允许一个NULL值,可以有多个候选键,同样有列级和表级两种完整性约束,下面再class表中给class_tech_no添加候选键约束,执行如下所示:
mysql> drop table class;
Query OK, 0 rows affected (0.01 sec)

mysql> create table class(
    -> class_no int primary key,
    -> class_count int null,
    -> class_tech_no int not null unique
    -> )engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)

mysql> drop table class;
Query OK, 0 rows affected (0.01 sec)

mysql> create table class(
    -> class_no int,
    -> class_count int null,
    -> class_tech_no int not null,
    -> constraint uq_class UNIQUE(class_tech_no)
    -> )engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)

参照完整性

参照完整性规则定义的是外键与主键之间的引用规则,即外键的取值或者为空,或者等于被参照关系中某个主键的值,同样有列级和表级两种完整性约束。定义外键时,需要遵循以下规则:
(1)被参照表必须已存在。
(2)必须是被参照表定义的主键或候选键。
(3)外键列和被参照表的主键或候选键数据类型相同。
比如:给class表的class_tech_no定义外键,执行如下所示:

mysql> drop table class;
Query OK, 0 rows affected (0.01 sec)

mysql> create table class(
    -> class_no int primary key,
    -> class_count int null,
    -> class_tech_no int not null references tb_tech(tech_no)
    -> )engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)

mysql> drop table class;
Query OK, 0 rows affected (0.01 sec)

mysql> create table class(
    -> class_no int primary key,
    -> class_count int null,
    -> class_tech_no int not null,
    -> constraint PK_tech foreign key(class_tech_no) references tb_tech(tech_no)
    -> )engine=InnoDB;
    Query OK, 0 rows affected (0.04 sec)

再class表上定义外键约束后,只有当tech表没有数据是时才可删除class数据,MySQL可以通过定义违约处理策略,来修改这个规则。
违约处理策略包括两部分:一是指定参照动作的语句(UPDATEDELETE);二是指定采取动作(RESTRICTCASCADESET NULLNO ACTIONSET DEFAULT),其中RESTRICT为默认值。具体策略如下:

  • RESTRICT:限制策略。被参照表有数据时,拒绝删除或修改操作。
  • CASCADE:级联策略。被参照表删除或修改记录时,自动删除或修改参照表的数据。
  • SET NULL:置空策略。被参照表删除或修改记录时,参照表的数据改为NULL。
  • NO ACTION:不采取实施策略。与限制策略相同。
  • SET DEFAULT:默认值策略。此策略要求定义默认值,被参照表删除或修改记录时,外键字段的值为默认值。
    比如:删除tb_tech表时,对应的外键字段采用置空策略。修改tb_tech表时,对应的外键字段采用级联策略。
mysql> create table class(
    -> class_no int primary key,
    -> class_count int null,
    -> class_tech_no int
    -> constraint PK_tech foreign key(class_tech_no) references tb_tech(tech_no)
    -> ON DELETE SET NULL
    -> ON UPDATE CASCADE
    -> )engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)

mysql> select * from class;
+----------+-------------+---------------+
| class_no | class_count | class_tech_no |
+----------+-------------+---------------+
|        1 |          22 |             1 |
+----------+-------------+---------------+
1 row in set (0.00 sec)

mysql> select * from tb_tech;
+---------+
| tech_no |
+---------+
|       1 |
|       2 |
+---------+
2 rows in set (0.00 sec)

mysql> update tb_tech set tech_no=11 where tech_no=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from class;
+----------+-------------+---------------+
| class_no | class_count | class_tech_no |
+----------+-------------+---------------+
|        1 |          22 |            11 |
+----------+-------------+---------------+
1 row in set (0.00 sec)

mysql> delete from tb_tech where tech_no =11;
Query OK, 1 row affected (0.01 sec)

mysql> select * from class;
+----------+-------------+---------------+
| class_no | class_count | class_tech_no |
+----------+-------------+---------------+
|        1 |          22 |          NULL |
+----------+-------------+---------------+
1 row in set (0.00 sec)

用户定义的完整性

用户定义完整性,满足了应用的语义需求,MySQL支持的几种用户定义完整性,分别是非空约束、CHECK约束和触发器。

  1. 设置非空约束
    再创建表或者修改表的时候给字段加上NOT NULL关键字,来约束列取值不能为空。执行如下所示:
mysql> create table tb_student(
    -> student_no int not null primary key auto_increment,
    -> student_name varchar(20) not null,
    -> age int not null,
    -> class_no varchar(10) default null
    -> )engine=Innodb;
Query OK, 0 rows affected (0.02 sec)
    
mysql> alter table tb_student add column id_no varchar(32) not null unique ;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0
  1. CHECK约束
    也是再创建表或者修改表的时候给字段加上CHECK关键字。执行如下所示:
mysql> create table tb_student(
    -> student_no int not null primary key auto_increment,
    -> student_name varchar(20) not null,
    -> age int not null CHECK(age >0 and age <25),
    -> class_no varchar(10) default null
    -> )engine=Innodb;
Query OK, 0 rows affected (0.02 sec)

更新完整性约束

当约束建立不符合要求时,可以使用 ALTER TABLE语句来更新有关约束。

  1. 删除约束

(1)删除主键约束

语法格式为:

ALTER TABLE 表名 DROP PRIMARY KEY;

比如:删除class表的class_no的主键约束,执行如下所示:

mysql> show create table class;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  PRIMARY KEY (`class_no`),
  KEY `PK_tech` (`class_tech_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table class drop primary key;
Query OK, 1 row affected (0.06 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> show create table class;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                     |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  KEY `PK_tech` (`class_tech_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

(2)删除外键约束

语法格式为:

ALTER TABLE 表名 DROP FOREIGN KEY 外键约束名;

比如:删除class表中class_tech_no的外键约束,执行如下所示:

mysql> show create table class;
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                             |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  PRIMARY KEY (`class_no`),
  KEY `PK_tech` (`class_tech_no`),
  CONSTRAINT `PK_tech` FOREIGN KEY (`class_tech_no`) REFERENCES `tb_tech` (`tech_no`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table class drop foreign key PK_tech;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table class;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  PRIMARY KEY (`class_no`),
  KEY `PK_tech` (`class_tech_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

(2)删除候选键约束

语法格式为:

ALTER TABLE 表名 DROP 候选键字段;

比如:删除class表class_count字段的候选键,执行如下所示:

mysql> show create table class;
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                         |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  UNIQUE KEY `PK_class_count` (`class_count`),
  KEY `PK_tech` (`class_tech_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table class drop class_count;
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table class;
+-------+-------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                        |
+-------+-------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_tech_no` int DEFAULT NULL,
  KEY `PK_tech` (`class_tech_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
  1. 添加约束

(1)添加主键约束

语法格式为:

ALTER TABLES 表名 ADD CONSTRAINT 约束名 PRIMARY KEY (主键字段);

比如:给class表的class_no字段加上主键约束,执行如下所示:

mysql> show create table class;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                  |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table class add constraint PK_class_no primary key(class_no);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table class;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                              |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  PRIMARY KEY (`class_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

(2)添加外键约束

语法格式为:

ALTER TABLES 表名 ADD CONSTRAINT 约束名 FOREIGN KEY (外键字段) REFERENCES 被参照表(主键字段);

比如:给class表的class_tech_no字段加上外键约束,执行如下所示:

mysql> show create table class;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                              |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  PRIMARY KEY (`class_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table class add constraint FK_class_tech_no foreign key(class_tech_no) references tb_tech(tech_no);
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table class;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                          |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  PRIMARY KEY (`class_no`),
  KEY `FK_class_tech_no` (`class_tech_no`),
  CONSTRAINT `FK_class_tech_no` FOREIGN KEY (`class_tech_no`) REFERENCES `tb_tech` (`tech_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

(3)添加候选键约束

语法格式为:

ALTER TABLES 表名 ADD CONSTRAINT 约束名 UNIQUE KEY (字段);

比如:给class表的class_count字段加上主键约束,执行如下所示:

mysql> show create table class;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                          |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  PRIMARY KEY (`class_no`),
  KEY `FK_class_tech_no` (`class_tech_no`),
  CONSTRAINT `FK_class_tech_no` FOREIGN KEY (`class_tech_no`) REFERENCES `tb_tech` (`tech_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table class add constraint UN_class_count unique key(class_no);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table class;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                                                      |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| class | CREATE TABLE `class` (
  `class_no` int NOT NULL,
  `class_count` int DEFAULT NULL,
  `class_tech_no` int DEFAULT NULL,
  PRIMARY KEY (`class_no`),
  UNIQUE KEY `UN_class_count` (`class_no`),
  KEY `FK_class_tech_no` (`class_tech_no`),
  CONSTRAINT `FK_class_tech_no` FOREIGN KEY (`class_tech_no`) REFERENCES `tb_tech` (`tech_no`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

索引

索引(Index)是数据库技术的一个重要概念与技术,也是MySQL的一个数据库对象。索引是查询优化的最主要的方式。

概述

对数据库中表进行查询时,系统对表中数据主要有两种搜索方式一种是全表扫描、检索,这种是将表的数据从头到尾逐行读取,这种查询效率就会降低;另一种是利用数据表上建立的索引进行扫描,根据索引值与记录关系直接访问数据表中的记录行。

如下图所示,比如查询学生编号为“2021002”的学生姓名,首先找到“2021002”在索引项的记录,在按照索引值与数据表之间的关系,之间找到“2021002”对应的数据记录。
在这里插入图片描述
在MySQL中索引分为普通索引、唯一索引、主键索引、聚族索引及全文索引等。
(1)普通索引
最基本的索引类型,索引列值可以取空值或重复值。创建普通索引时,通常使用的关键字是INDEXKEY
(2)唯一索引
索引列值不能重复,唯一的,可以是空值。关键字是UNIQUE.
(3)主键索引
主键索引是一种唯一索引。与唯一索引不同的是引用列值不能为空。关键字为PRIMARY KEY
(4)聚族索引
索引的顺序就是数据存储的物理存储顺序,这样能保证索引值相近的元组所存储的物理位置也相近。并非所有存储引擎支持聚族索引,目前只有solidDB和InnoDB。
(5)全文索引
只能创建在数据类型为VARCHARTEXT的列上。建立全文索引后,能够在建立的列上进行全文查找。

在实际使用中,索引可以建立在单一列上,称为单列索引。也可以建立在多个列上,称为组合索引。
(1)单列索引
一个索引只包含原表中的一个列。一个表上可以建立多个单列索引。比如,在学生表中建立学号索引,还可以建立班级索引。
(2)组合索引
在表的多个列上创建一个索引。比如,班级表的“班号”和“班主任编号”建立一个索引,称为组合索引。

查看表的索引

语法格式为:

SHOW {
   
   INDEX|INDEXES|KEYS} {
   
   FROM | IN} 表名 [{
   
   FROM | IN} 表名];

比如:查看学生表的索引,\G按列打印,方便查询。执行结果如下所示:

mysql> show index from  student\G;
*************************** 1. row ***************************
        Table: student #表名称
   Non_unique: 0 #是否唯一索引。是:1,否:0
     Key_name: PRIMARY # 索引名称
 Seq_in_index: 1
  Column_name: student_no #建立索引的列名
    Collation: A #顺序索引 升序:A 
  Cardinality: 6 # 数据行数
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE # 索引类型 B+树
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL
1 row in set (0.00 sec)

创建索引

MySQL提供了三种创建索引的方法。一种是创建表的时候创建索引,另外两种分别是在已存在的表上建立索引,使用CREATE INDEXALTER TABLE添加索引。

  1. 使用CAEATE TABLE创建索引
    语法格式为:
CREATE TABLE 表名(
字段名 数据类型 [列级完整性约束条件] [默认值],
... ...
[CONSTRAINT 索引名][UNIQUE] [INDEX |KEY]
[索引名](列名)[ASC|DESC]
)ENGINE = 引擎类型;

比如:创建tb_student_1的表建立主键、唯一索引。执行结果如下所示:

mysql> create table tb_student_1(
    -> student_no int not null primary key unique auto_increment,
    -> student_name varchar(20) not null,
    -> age int not null,
    -> class_no varchar(10) default null
    -> )engine=Innodb;
Query OK, 0 rows affected (0.02 sec)

mysql> show index from tb_student_1 \G;
*************************** 1. row ***************************
        Table: tb_student_1
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: student_no
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL
*************************** 2. row ***************************
        Table: tb_student_1
   Non_unique: 0
     Key_name: student_no
 Seq_in_index: 1
  Column_name: student_no
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL
2 rows in set (0.01 sec)
  1. 使用CERATE INDEX创建索引
    语法格式为:
CREATE [UNIQUE] INDEX 索引名 ON 表名(列名[ASC|DESC]);

比如:创建老师表的编号的唯一降序索引。执行结果如下所示:

mysql> create unique index un_tech on tech(tech_no desc);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from tech \G;
*************************** 1. row ***************************
        Table: tech
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: tech_no
    Collation: A
  Cardinality: 6
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL
*************************** 2. row ***************************
        Table: tech
   Non_unique: 0
     Key_name: un_tech
 Seq_in_index: 1
  Column_name: tech_no
    Collation: D
  Cardinality: 6
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL
2 rows in set (0.00 sec)
  1. 使用ALTER TABLE创建索引
    语法格式为:
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT] [INDEX | KEY] [索引名](列名[ASC|DESC]);

比如:给老师表的老师名称加上唯一索引。执行结果如下所示:

mysql> alter table tech add unique un_tech_name(tech_name);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0
#省略多余结果,可参考上面
*************************** 3. row ***************************
        Table: tech
   Non_unique: 0
     Key_name: un_tech_name
 Seq_in_index: 1
  Column_name: tech_name
    Collation: A
  Cardinality: 6
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL
3 rows in set (0.00 sec)

删除索引

  1. 使用DEOP INDEX语句删除索引
    语法格式为:
DROP INDEX 索引名 ON 表名;

比如:删除老师表的老师名称索引。执行结果如下所示:

mysql> drop index un_tech_name on tech;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0
  1. 使用ALTER TABLE语句删除索引
    语法格式为:
ALTER TABLE 表名 DROP INDEX 索引名;

比如:删除老师表的老师编号索引。执行结果如下所示:

mysql> alter table tech drop index un_tech;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from tech \G;
*************************** 1. row ***************************
        Table: tech
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: tech_no
    Collation: A
  Cardinality: 6
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL
1 row in set (0.00 sec)

可以看到之前创建的两个索引都删除了。

对索引的建议

使用索引可以大大加快查询速度,提高MySQL的检索性能,但过多的使用反而会影响系统性能。

  1. 索引的问题
    (1)降低更新表数据的速度
    提高查询同时降低更新表的速度。如果建立过多的索引,降低INSERTUPDATEDELETE的效率。
    (2)增加存储空间
    索引需要占用磁盘空间,大量的索引,会使索引文件膨胀的非常快。
  2. 使用索引建议
    (1)避免过多建立索引
    (2)数据量小,最后不要建立索引
    (3)避免使用通配符,会使索引失效
    (4)一些文本数据类型,可以对字段前N个字符进行索引,节约存储空间

章节目录

上一篇:MySQL数据库程序设计(一)
下一篇:MySQL数据库程序设计(三)

猜你喜欢

转载自blog.csdn.net/qq_39940674/article/details/120245235