文章目录
什么是数据库
-
数据库概述:数据库是按照一定的数据结构将数据存储在存储器的集合
-
常见数据库软件
软件名 | 开源 | 跨平台 | 厂 商 |
---|---|---|---|
Oracle | 否 | 是 | 甲骨文 |
MySQL | 是 | 是 | 甲骨文 |
SQL Server | 否 | 否 | 微软 |
DB2 | 否 | 是 | IBM |
openGauss | 是 | 是 | 华为 |
Redis | 是 | 是 | 开源软件 |
Memcached | 是 | 是 | 开源软件 |
openGauss | 是 | 是 | 华为 |
-
DB (DataBase)
- 数据库
- 依照某种数据模型进行组织并存放到存储器的数据集合
-
DBMS (DataBase Management System)
-
数据库管理系统
-
用来操纵和管理数据库的服务软件
-
-
DBS (DataBase System)
- 数据库系统:即 DB+DBMS
- 指带有数据库并整合了数据库管理软件的计算机系统
MySQL介绍
- 主要特点
- 适用于中小规模、关系型数据库系统
- 支持Linux、Unix、Windows等多种操作系统
- 支持Python、Java、Perl、PHP等编程语言
- LAMP平台,与Apache HTTP Server组合
- LNMP平台,与Nginx组合
实验环境准备
- 使用CentOS7.9模板机克隆mysql虚拟机,配置信息如下
主机名 | 内网IP地址 |
---|---|
mysql | 192.168.8.100(VMnet8网络模式) |
配置基础环境
shell
[root@localhost ~]# hostnamectl set-hostname mysql
[root@mysql ~]# nmcli connection modify ens33 ipv4.method auto connection.autoconnect yes
[root@mysql ~]# nmcli connection up ens33
配置yum,使用阿里云的镜像站点
shell
[root@localhost ~]# rm -rf /etc/yum.repos.d/*.repo #删除自带的repo文件
[root@localhost ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo \ https://mirrors.aliyun.com/repo/Centos-7.repo #下载阿里镜像源
构建MySQL服务
将学习环境中的:C-4软件运维\05_医疗项目\HIS医疗项目\mysql8-centos7上传到虚拟机mysql的/root/
mysql主机操作
shell
[root@mysql ~]# cd /root/mysql8-centos7
[root@mysql ~]# yum -y localinstall *.rpm #安装mysql
[root@mysql ~]# systemctl start mysqld #启动服务
[root@mysql ~]# systemctl enable mysqld #开机运行
[root@mysql ~]# ss -utnlp | grep :3306 #查看服务信息
软件相关的目录与文件等
文件 | 说明 |
---|---|
主配置文件 | /etc/my.cnf.d/mysql-server.cnf |
数据库目录 | /var/lib/mysql |
端口号 | 3306 |
进程名 | mysqld |
传输协议 | TCP |
进程所有者 | mysql |
进程所属组 | mysql |
错误日志文件 | /var/log/mysql/mysqld.log |
连接数据库
-
数据库管理员名为 root
-
连接命令: mysql -h数据库地址 -u用户 -p密码
-
首次启动之后数据库管理root的密码存放再/var/log/mysqld.log中
-
连接时不指定密码,默认为无密码
shell
[root@mysql mysql8-centos7]# grep -i password /var/log/mysqld.log #过滤root初始密码
2023-08-08T14:22:39.197619Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: 3Izdh9OY6&Ef
连接mysql(每个人过滤到的mysql管理员root的初始密码都是随机的,不要照抄,建议加上'')
shell
[root@mysql ~]# mysql -uroot -p'3Izdh9OY6&Ef'
修改root密码
- 格式:使用 ALTER USER 用户@"主机" IDENTIFIED BY "密码";
- 新密码必须满足密码策略
- 管理员root 使用新密码连接服务
shell
mysql> ALTER USER root@"localhost" IDENTIFIED BY "tedu123...A"; #修改登陆密码
[root@mysql ~]# mysql -hlocalhost -uroot -p'tedu123...A' #使用新密码登陆
数据库基础
常用的SQL命令分类
-
管理数据库使用SQL(结构化查询语言)
-
DDL 数据定义语言 如:CREATE、ALTER、DROP
-
DML 数据操作语言 如:INSERT、UPDATE、DELETE
-
DCL 数据控制语言 如:GRANT、REVOKE
-
DTL 数据事务语言 如:COMMIT、ROLLBACK、SAVEPOINT
SQL命令使用规则
-
SQL命令不区分字母大小写(密码、变量值除外)
-
每条SQL命令以;结束
-
默认命令不支持Tab键自动补齐
-
\c 终止sql命令
MySQL基本操作
- 可以创建多个库,通过库名区分
SHOW DATABASES;
#显示已有的库SELECT USER();
#显示连接用户USE 库名;
#切换库SELECT DATABASE();
#显示当前所在的库CREATE DATABASE 库名;
#创建新库SHOW TABLES;
#显示已有的表DROP DATABASE 库名;
#删除库
创建库
- 库命名规则
- 仅可以使用数字、字母、下划线、不能纯数字
- 区分字母大小写,具有唯一性
- 不可使用指令关键字、特殊字符
sql
mysql> CREATE DATABASE DB1; #创建库DB1
Query OK, 1 row affected (0.06 sec)
mysql> CREATE DATABASE db1; #创建库db1
Query OK, 1 row affected (0.03 sec)
mysql> CREATE DATABASE haha; #创建库haha
Query OK, 1 row affected (0.03 sec)
sql
mysql> USE DB1; #切换至DB1库
mysql> SHOW TABLES; #查看DB1库里有哪些表
mysql> DROP DATABASE haha; #删除库haha
sql
mysql> SELECT USER(); #查看当前登录数据库的用户
SELECT DATABASE(); #查看当前所在库
创建表
- 格式
sql
mysql> CREATE TABLE 库名.表名(
字段名1 类型(宽度),
字段名2 类型(宽度),
......
)DEFAULT CHARSET=utf8;
创建db1.stuinfo表,包含name字段、homeaddr字段,指定字符集为utf8
sql
mysql> CREATE TABLE db1.stuinfo(
-> name CHAR(15),
-> homeaddr CHAR(20)
-> ) DEFAULT CHARSET=utf8;
查看表结构
- DESC 库名.表名;
shell
mysql> DESC db1.stuinfo;
+----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+-------+
| name | char(15) | YES | | NULL | |
| homeaddr | char(20) | YES | | NULL | |
+----------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)
记录管理命令
-
查询
SELECT * FROM 库名.表名;
-
插入
INSERT INTO 库名.表名 VALUES(值列表);
-
修改
UPDATE 库名.表名 SET 字段=值;
-
删除
DELETE FROM 表名;
向db1.stuinfo表里插入一行记录
sql
mysql> INSERT INTO db1.stuinfo VALUES("sam","Beijing");
查询db1.stuinfo表格里的所有数据
sql
mysql> SELECT * FROM db1.stuinfo;
修改db1.stuinfo表格里边的homeaddr字段内容为"Shanghai"
sql
mysql> UPDATE db1.stuinfo SET homeaddr="Shanghai";
删除db1.stuinfo表里边的所有数据
sql
mysql> DELETE FROM db1.stuinfo;
mysql> SELECT * FROM db1.stuinfo; #查看验证
数据类型
- 定长:
CHAR
(字符个数)- 最大字符个数255
- 不够指定字符个数时在右边用空格补全
- 字符个数超出时,无法写入数据。
sql
mysql> CREATE TABLE db1.t1(name char(5) , homedir CHAR(50) ); #创建表格
mysql> INSERT INTO db1.t1 VALUES("bob","USA"); #写入数据
-
变长:
VARCHAR
(字符个数)-
按数据实际大小分配存储空间(0-65535)
-
字符个数超出时,无法写入数据。
-
大文本类型:text/blob
-
字符数大于65535存储时使用
-
创建db1.t2表,包含name CHAR(5)、email VARCHAR(30)
sql
mysql> CREATE TABLE db1.t2(name CHAR(5),
-> email VARCHAR(30)
-> );
mysql> INSERT INTO db1.t2 VALUES("lucy","lucy@tedu.cn");
数值类型
- 整数型
类 型 | 名称 | 有符号范围 | 无符号范围 |
---|---|---|---|
TINYINT | 微小整数 | -128~127 | 0 ~ 255 |
SMALLINT | 小整数 | -32768~32767 | 0 ~ 65535 |
MEDIUMINT | 中整型 | -223 ~ 223-1 | 0 ~ 224-1 |
INT | 大整型 | -231 ~ 231-1 | 0 ~ 232-1 |
BIGINT | 极大整型 | -263 ~ 263-1 | 0 ~ 264-1 |
UNSIGNED | 使用无符号存储范围 |
- 浮点数
类 型 | 名称 | 有符号范围 | 无符号范围 |
---|---|---|---|
FLOAT | 单精度 | -3.402823466E+38 到 -1.175494351E-38 | 1.175494351E-38 到 3.402823466E+38 |
DOUBLE | 双精度 | -1.7976931348623157E+308到 -2.2250738585072014E-308 | 2.2250738585072014E-308 到 1.7976931348623157E+308 |
sql
mysql> CREATE TABLE db1.t3(pay FLOAT , id DOUBLE);
mysql> CREATE TABLE db1.t4(pay FLOAT(5,2) , id DOUBLE(4,2) );
数据类型
日期时间类型
- 日期
DATE
- 范围:0001-01-01 ~ 9999-12-31
- 格式: yyyy-mm-dd 1949-10-01
- 年
YEAR
- 范围:1901~2155
- 格式:yyyy 1998 2000
- 要求使用4位数赋值
- 当使用2位数赋值时:01-99(1970-2069某个年份)
- 00~69视为 2000~2069
- 70~99视为 1970~1999
- 时间
TIME
- 格式:HH:MM:SS 22:18:28
- 日期时间
DATETIME
- 范围:1000-01-01 00:00:00~ 9999-12-31 23:59:59
- 格式: "YYYY-MM-DD HH:MM:SS"
- 日期时间
TIMESTAMP
- 范围:1970-01-01 00:00:00 ~ 2038-01-19 00:00:00
- 格式: "YYYY-MM-DD HH:MM:SS"
- 当未给TIMESTAMP类型字段赋值时,自动以当前系统时间赋值,而DATETIME 值为 NULL (空)
时间函数
- 函数服务内置的命令,可以使用时间函数给字段赋值
类 型 | 用 途 |
---|---|
CURTIME( ) | 获取当前的系统时间"时:分:秒"部分 |
CURDATE( ) | 获取当前的系统时间"年-月-日"部分 |
NOW( ) | 获取当前系统时间"年-月-日 时:分:秒" |
YEAR(NOW()) | 获取年 |
MONTH(NOW( )) | 获取月 |
DAY(NOW()) | 获取日 |
DATE(NOW()) | 获取日期"年-月-日" |
TIME(NOW()) | 获取时间"时:分:秒" |
shell
[root@mysql ~] mysql -uroot -p'密码' #连接数据库
mysql> SELECT CURTIME(); #查看"时:分:秒"
mysql> SELECT CURDATE(); #查看"年-月-日"
mysql> SELECT NOW(); #查看"年-月-日 时:分:秒"
mysql> SELECT YEAR(NOW()); #查看"年-月-日 时:分:秒"
案例
- 新建库bbsdb
sql
[root@mysql ~]# mysql --uroot --p密码 #连接数据库
mysql> CREATE DATABASE bbsdb; #创建库bbsdb
- 创建bbsdb.t5表
- 包含name字段 CHAR(15)类型
- 包含s_year字段 YEAR类型
- 包含school_time字段 TIME类型
- 包含birthday字段 DATE类型
- 包含party DATETIME类型
创建bbsdb.t5表
sql
mysql> CREATE TABLE bbsdb.t5(name CHAR(15),s_year YEAR,
-> school_time TIME, birthday DATE,
-> party DATETIME);
向bbsdb.t5表插入数据
sql
mysql> INSERT INTO bbsdb.t5 VALUES("sam",1980,"19:00:00",
-> "1980-10-06","2029-06-18 12:05:16");
查询bbsdb.t5表数据
sql
mysql> SELECT * FROM bbsdb.t5;
+------+--------+-------------+------------+---------------------+
| name | s_year | school_time | birthday | party |
+------+--------+-------------+------------+---------------------+
| sam | 1980 | 19:00:00 | 1980-10-06 | 2029-06-18 12:05:16 |
+------+--------+-------------+------------+---------------------+
1 row in set (0.00 sec)
枚举类型
- ENUM 单选
- 格式:字段名 ENUM(值1, 值2, 值N)
- 仅能在列表里选择一个值
创建db1.t5表,包含name字段 CHAR类型15个宽度,sex字段单选枚举类型("boy","girl","other")
SQL
mysql> CREATE TABLE db1.t5(
-> name CHAR(15),
-> sex ENUM("boy","girl","other")
-> );
向db1.t5表插入数据
sql
mysql> INSERT INTO db1.t5 VALUES("sam","boy");
- SET 多选
- 格式:字段名 SET(值1, 值2, 值N)
- 在列表里选择一个或多个值
创建db1.t6表,包含name字段CHAR类型5个宽度,likes字段多选枚举类型("eat", "game" , "music", "money")
sql
mysql> CREATE TABLE db1.t6(
-> name CHAR(5),
-> likes SET("eat", "game" , "music", "money" )
-> );
向db1.t6表插入数据
sql
mysql> INSERT INTO db1.t6 VALUES("lisi","eat,game,music");
约束条件
NULL
允许为空(默认设置)NOT NULL
不允许为空KEY
键值类型DEFAULT
设置默认值,缺省为NULLEXTRA
额外设置
案例
- 创建db1.t7表
- name字段 CHAR类型10个宽度,不允许为空
- age字段 TINYINT类型无符号范围,默认值19
- class字段CHAR类型7个宽度,不允许为空,默认值为"nsd"
- pay字段FLOAT(7,2)类型,默认值为28000
sql
mysql> CREATE TABLE db1.t7(
-> name CHAR(10) NOT NULL,
-> age TINYINT UNSIGNED DEFAULT 19,
-> class CHAR(7) NOT NULL DEFAULT "nsd",
-> pay FLOAT(7,2) DEFAULT 28000
-> );
插入数据,不使用默认值
sql
mysql> INSERT INTO db1.t7 VALUES ('Alice', 22, 'nsd', 35000.50);
插入数据,使用默认值
sql
mysql> INSERT INTO db1.t7(name) VALUES("Bob");
查询db1.t7表中的数据
sql
mysql> SELECT * FROM db1.t7;
+-------+------+-------+----------+
| name | age | class | pay |
+-------+------+-------+----------+
| Alice | 22 | nsd | 35000.50 |
| Bob | 19 | nsd | 28000.00 |
+-------+------+-------+----------+
2 rows in set (0.00 sec)
修改表结构
- 格式:
mysql> ALTER TABLE 库名.表名 执行动作;
- 执行动作
ADD
添加字段MODIFY
修改字段类型CHANGE
修改字段名DROP
删除字段RENAME
修改表名
添加新字段ADD
- 新字段默认添加在字段末尾
- mysql> ALTER TABLE 库名.表名 ADD 字段名 类型(宽度) 约束条件 [ AFTER 字段名 | FIRST ] ;
修改db1.t6表,在likes字段后,添加home字段VARCHAR类型20个宽度
sql
mysql> ALTER TABLE db1.t6 ADD home VARCHAR(20) AFTER likes;
修改字段类型MODIFY
- mysql> ALTER TABLE 库名.表名 MODIFY 字段名 类型(宽度) 约束条件 [ AFTER 字段名 | FIRST ] ;
- 注:修改的字段类型不能与已存储的数据冲突
修改db1.t6表结构,将home字段修改为CHAR类型,30个宽度
sql
mysql> ALTER TABLE db1.t6 MODIFY home CHAR(30) ;
删除字段DROP
- mysql> ALTER TABLE 库名.表名 DROP 字段名 ;
- 表中有多条记录时,所有列的此字段的值都会被删除
删除db1.t6表中的home字段
sql
mysql> ALTER TABLE db1.t6 DROP home ;
修改字段名CHANGE
- mysql> ALTER TABLE 库名.表名 CHANGE 原字段名 新字段名 类型 约束条件 ;
修改db1.t6表中name字段为user,VARCHAR类型30个宽度
sql
mysql> ALTER TABLE db1.t6 CHANGE name user VARCHAR(30);
修改表名RENAME
- 表对应的文件名,也被改变
- 表记录不受影响
- mysql> ALTER TABLE 表名 RENAME 新表名
修改db1.t6表名为db1.userinfo
sql
mysql> ALTER TABLE db1.t6 rename db1.userinfo;
普通索引
- index 普通索引
- unique 唯一索引
- fulltext 全文索引
- primary key 主键
- foreign key 外键
索引概述
- 类似于书的目录
- 对表中字段值进行排序。
- 索引算法:Btree、B+tree 、hash
索引的特点
- 索引优点
- 可以加快数据的查询速度
- 索引缺点
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态的调整,降低了数据的维护速度
- 索引需要占物理空间
建表时创建普通索引
- 具体要求如下:
- 一个表中可以有多个index字段
- 字段的值允许重复,且可以赋NULL值
- index字段 标志是 MUL
- 通常把做为查询条件的字段设置为index字段
- 建表时创建索引
- INDEX(字段名), INDEX(字段名) ... ...
- 创建db1.t9其中包含
- id字段,CHAR类型,宽度为 6,不能为空。该字段被定义为一个索引。
- name字段,VARCHAR类型,宽度为 4,不能为空。该字段也被定义为一个索引。
- age字段INT类型,不能为空。
- gender字段ENUM类型,只能是 "male" 或者 "female"。该字段可以为空
sql
mysql> CREATE TABLE db1.t9( id CHAR(6) NOT NULL,
-> name VARCHAR(4) NOT NULL, age INT NOT NULL,
-> gender ENUM("male","female"), INDEX(id),INDEX(name));
在已有表创建/删除索引
- 创建索引:
CREATE INDEX 索引名 ON 表名(字段名);
- 删除索引:
DROP INDEX 索引名 ON 表名;
在db1.t9表中将age字段设置为索引字段,索引名为age_index
sql
mysql> CREATE INDEX age_index ON db1.t9 (age);
删除db1.t9表中的age_index字段
sql
mysql> DROP INDEX age_index ON db1.t9;
查看索引信息
SHOW INDEX FROM 库名.表名 \G;
- 注:\G表示以垂直格式输出查询结果
查看db1.t9表索引
sql
mysql> SHOW INDEX FROM db1.t9 \G
高级字段约束
主键
- 主键约束:用于保证字段值具有唯一性并且非空,一张表中只能有一个主键
单列主键测试
mysql
mysql> CREATE DATABASE execdb; #创建execdb
mysql> USE execdb; #使用execdb库
mysql> CREATE TABLE t4 (name CHAR(5) PRIMARY KEY); #设置主键约束语法1
mysql> DESC t4;
mysql> CREATE TABLE t5 (name CHAR(5),PRIMARY KEY(name)); #设置主键约束语法2
mysql> DESC t5;
mysql> INSERT INTO t5 VALUES ('zhsan'); #写入成功
mysql> INSERT INTO t5 VALUES ('zhsan'); #值重复,写入失败
ERROR 1062 (23000): Duplicate entry 'zhsan' for key 'PRIMARY'
mysql> INSERT INTO t5 VALUES (NULL); #值为空,写入失败
ERROR 1048 (23000): Column 'name' cannot be null
mysql> ALTER TABLE t5 DROP PRIMARY KEY; #删除已有主键
mysql> DESC t5;
mysql> ALTER TABLE t5 ADD PRIMARY KEY(name); #添加主键约束
mysql> DESC t5;
复合主键测试(多字段组合结果不重复即可)
sql
mysql> CREATE TABLE execdb.t6 (
-> user CHAR(10),
-> host CHAR(15),
-> status ENUM('allow','deny') NOT NULL DEFAULT "deny",
-> PRIMARY KEY(user,host)
-> ); #创建execdb.t6表测试复合主键
mysql> DESC t6;
mysql> INSERT INTO t6 VALUES
-> ('abc','1.1.1.1','allow'),
-> ('abc','1.1.1.2','deny'),
-> ('haha','1.1.1.1','deny'); #写入成功
mysql> INSERT INTO t6 VALUES
-> ('haha','1.1.1.1','allow'); #组合结果与已有数据冲突,写入失败
ERROR 1062 (23000): Duplicate entry 'haha-1.1.1.1' for key 'PRIMARY'
mysql> ALTER TABLE t6 DROP PRIMARY KEY; #删除已有复合主键
mysql> DESC t6;
mysql> ALTER TABLE t6 ADD PRIMARY KEY(user,host); #向已有表添加复合主键
mysql> DESC t6;
自增长测试
sql
mysql> CREATE TABLE t7 (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name CHAR(10)
-> ); #PRIMARY KEY与AUTO_iNCREMENT联用
mysql> DESC t7;
mysql> CREATE TABLE t8(
-> id INT AUTO_INCREMENT,
-> name CHAR(10),
-> PRIMARY KEY(id)
-> ); #PRIMARY KEY与AUTO_INCREMENT分开用
mysql> DESC t8;
mysql> INSERT INTO t8(name) VALUES ('bob'); #id从1开始
mysql> INSERT INTO t8(name) VALUES ('tom'); #id为2
mysql> SELECT * FROM t8;
mysql> INSERT INTO t8 VALUES (10,'jim'); #可以指定id赋值
mysql> INSERT INTO t8(name) VALUES ('john'); #识别id字段最大值
mysql> SELECT * FROM t8;
mysql> DELETE FROM t8; #清空表记录,验证自增长是否重置
mysql> INSERT INTO t8(name) VALUES ('haha'); #测试写入
mysql> SELECT * FROM t8; #自增长未重置
mysql> TRUNCATE TABLE t8; #TRUNCATE语句快速清表
mysql> INSERT INTO t8(name) VALUES ('haha'); #测试写入记录
mysql> SELECT * FROM t8; #id自增长重置
mysql> DELETE FROM t8;
#主键不一定自增,但被标记自增的一定是主键
外键
- 外键约束:保证数据的一致性,外键字段值必须在参考表中字段已有值里选择,一张表中可以有多个外键
- 表存储引擎必须是innodb (在进阶课程里讲 现在仅需要知道如何指定表使用innodb存储引擎)
- 外键表字段与被关联表字段类型要一致
- 被参照字段必须要是索引类型的一种(通常是PRIMARY KEY)
mysql
mysql> SHOW VARIABLES LIKE "default_storage_engine";
+------------------------+--------+
| Variable_name | Value |
+------------------------+--------+
| default_storage_engine | InnoDB |
+------------------------+--------+
1 row in set (0.00 sec)
在execdb中,创建员工表emp(包含ID字段,INT类型,主键,自增长;name字段CHAR类型20个宽度)
在execdb中,创建工资表salary(包含id字段 ,INT类型,wage字段,FLOAT类型)
将execdb.salary表的id字段设置为外键,依赖于execdb.emp表的id字段
sql
mysql> USE execdb; #切换到练习库
mysql> CREATE TABLE emp (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name CHAR(20)
-> ); #创建练习emp表,用于存储员工信息
Query OK, 0 rows affected (0.00 sec)
mysql> DESC emp; #查看emp表结构
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | char(20) | YES | | NULL | |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> CREATE TABLE salary(
-> id INT,
-> wage FLOAT,
-> FOREIGN KEY(id) REFERENCES emp(id)
-> ON UPDATE CASCADE
-> ON DELETE CASCADE
-> ); #创建练习salary表,用于存储员工某个月工资
Query OK, 0 rows affected (0.00 sec)
mysql> DESC salary; #查看salary表结构
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | MUL | NULL | |
| wage | float | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
##测试外键约束
mysql> INSERT INTO salary VALUES (1,5000); #写入失败,emp表中id字段无值
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`execdb`.`salary`, CONSTRAINT `salary_ibfk_1` FOREIGN KEY (`id`) REFERENCES `emp` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
mysql> INSERT INTO emp(name) VALUES ('zhangsan'),('lisi'); #添加员工记录(一次插入2行)
mysql> SELECT * FROM emp; #查看已有员工记录
mysql> INSERT INTO salary VALUES (1,5000); #给id是1的员工发5000,成功
mysql> INSERT INTO salary VALUES (2,4000); #给id是2的员工发4000,成功
##验证级联更新(ON UPDATE CASCADE)
mysql> SELECT * FROM emp; #查询emp表记录
mysql> SELECT * FROM salary; #查询salary表记录
mysql> UPDATE emp SET id=5 WHERE name='lisi'; #更新emp表中lisi用户id为5
mysql> SELECT * FROM emp; #确认emp表中lisi的id已更新为5
mysql> SELECT * FROM salary; #此过程中并未操作salary表,但数据已发生变化
##验证级联删除(ON DELETE CASCADE)
mysql> SELECT * FROM emp; #查询emp表记录
mysql> SELECT * FROM salary; #查询salary表记录
mysql> DELETE FROM emp WHERE id=5; #删除emp表中id为5的表记录
mysql> SELECT * FROM emp; #确认id为5的记录被删除
mysql> SELECT * FROM salary; #此过程中并未操作salary表,但数据已发生变化
##外键操作语法
mysql> SHOW CREATE TABLE salary; #查看完整建表语句
mysql> ALTER TABLE salary DROP FOREIGN KEY `salary_ibfk_1`; #删除指定外键
mysql> SHOW CREATE TABLE salary; #查看完整建表语句
mysql> ALTER TABLE salary
-> ADD FOREIGN KEY(id) REFERENCES emp(id)
-> ON UPDATE CASCADE ON DELETE CASCADE; #向已有表添加外键
mysql> SHOW CREATE TABLE salary; #查看完整建表语句
##注意事项
mysql> DROP TABLE emp; #被关联表不允许删除
ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails
mysql>
mysql> SELECT * FROM salary; #查看salary表记录
mysql> INSERT INTO salary VALUES (1,2000); #给员工重复发工资
mysql> SELECT * FROM salary; #重复工资下发成功,该现象不合理
mysql> DESC salary; #查看salary表结构,id字段不能重复(PRIMARY KEY)
mysql> ALTER TABLE salary ADD PRIMARY KEY(id); #给salary表id字段添加主键,失败,数据重复
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> DELETE FROM salary WHERE wage=2000; #清理重复数据
mysql> ALTER TABLE salary ADD PRIMARY KEY(id); #给salary表id字段添加主键,成功
mysql> DESC salary; #查看salary表结构,id字段标签
mysql> INSERT INTO salary VALUES (1,2000); #再次测试重复工资,下发失败
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> SHOW CREATE TABLE salary; #查看salary建表语句
#PRIMARY KEY和FOREIGN KEY可以共存
总结
- 搭建MySQL数据库服务器
- 数据库基础
- 掌握MySQ基本管理命令
- 数据类型(字符类型、数值类型、浮点型)
- 掌握修改表结构
- 掌握索引的作用
- 掌握主键与外键的作用及使用方法