【MySQL】主键、唯一键和外键

文章目录

  • 主键
  • 唯一键
  • 外键


主键

作用:

在一个table中,标识一行记录的唯一性。

语法:

create table时,可以紧随列属性声明的后面,如id int primary key ,也可以单独成一行,如下:

mysql> show create table student \G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (`id` int(3) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL,`gender` enum('男','女') DEFAULT NULL,PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
  • 表已存在,添加主键

    alter table 表名 add primary key (已存在的字段列表);
    
  • 删除主键

    alter table 表名 drop primary key;
    

复合主键:

mysql> show create table t3 \G
*************************** 1. row ***************************
Table: t3
Create Table: CREATE TABLE `t3` (`course` varchar(20) NOT NULL,`name` varchar(20) NOT NULL,`gender` enum('男','女') DEFAULT NULL,PRIMARY KEY (`course`,`name`) #括号里面以逗号区分复合主键的每一个成分
) ENGINE=InnoDB DEFAULT CHARSET=utf8

多个属性组合为一个整体,以标识数据记录的唯一性,就是复合主键。要将复合主键看作一个整体,即复合主键也只是一个主键,只不过包含了多个属性。


唯一键

作用:

保证同一张table内,多条数据的某个字段的唯一性。

语法(和定义主键的语法差不多):

mysql> show create table student \G
*************************** 1. row ***************************Table: student
Create Table: CREATE TABLE `student` (`id` int(3) NOT NULL AUTO_INCREMENT,`name` varchar(20) NOT NULL,`gender` enum('男','女') DEFAULT NULL,`telephone` char(11) DEFAULT NULL,`wechat` varchar(15) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `telephone` (`telephone`),UNIQUE KEY `wechat` (`wechat`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
  • 添加唯一键

    alter table 表名 add unique key (已存在的字段列表);
    

复合唯一键:

道理和复合主键类似,也支持整合多个字段为一个唯一键(如下,创建一个学生信息表,以’班级-班内编号’作为一个复合唯一键)

mysql> show create table t4 \G
*************************** 1. row ***************************Table: t4
Create Table: CREATE TABLE `t4` (`id` int(3) unsigned zerofill NOT NULL,`name` varchar(20) NOT NULL,`class` char(10) DEFAULT NULL,`classid` tinyint(3) unsigned DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `in_class` (`class`,`classid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> select * from t4;
+-----+--------+------------+---------+
| id  | name   | class      | classid |
+-----+--------+------------+---------+
| 001 | 张三   | 2021200101 |       1 |
| 002 | 李四   | 2021200103 |       1 |
| 008 | 老刘   | 2021200103 |       2 |
+-----+--------+------------+---------+

每个学生的class可以相同,classid可以相同,但是class-classid组合起来就必须是唯一的。

The difference between primary key and unique key:

  1. 主键不允许为NULL,唯一键允许为NULL
  2. 一个table中,主键只能有一个(包括复合主键),唯一键可以有多个
  3. 主键侧重于标识一条记录(一行)的唯一性;而唯一键侧重于保证在业务上,某个属性在多个记录中的唯一

tips

  1. 主键和唯一键一般在字段插入具体数据之前指定(最好是建表时指定),否则可能会发生已经存在重复数据,再指定key。
  2. 主键和唯一键都有复合的形式,这在业务逻辑中很常见,比如,某个班的某个同学,他的‘班级号-班内编号’组合一定是唯一的。
  3. 一般而言,我们建议将主键设计成为和当前业务无关的字段,这样,当业务调整的时候,我们可以尽量不会对主键做过大的调整 。
  4. 删除主键和唯一键的动作很危险,要谨慎。

外键

作用:

在表与表之间建立联系,使彼此的增删查改操作受到另一方一定的影响。在foreign key的语境中,会有一张主表和一张从表,外键约束主要定义在从表上,主表则必须是有主键约束或唯一键约束,从表可以引用主表的primary key或unique key作为自己的外键,以此建立与主表的联系。

Demo场景:学生与班级的关系,学生一定从属于某个存在的班级。

从表指定外键的语法

foreign key (字段名) references 主表名(字段名)

建立主表class

mysql> show create table class \G
*************************** 1. row ***************************
Table: class
Create Table: CREATE TABLE `class` (`id` tinyint(3) unsigned zerofill NOT NULL,`type` enum('实验班','普通班') DEFAULT '普通班',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mysql> desc class;
+-------+-------------------------------+------+-----+-----------+-------+
| Field | Type                          | Null | Key | Default   | Extra |
+-------+-------------------------------+------+-----+-----------+-------+
| id    | tinyint(3) unsigned zerofill  | NO   | PRI | NULL      |       |
| type  | enum('实验班','普通班')       | YES  |     | 普通班    |       |
+-------+-------------------------------+------+-----+-----------+-------+

建立从表student

mysql> show create table student \G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (`id` int(3) NOT NULL AUTO_INCREMENT,`name` varchar(20) NOT NULL,`gender` enum('男','女') DEFAULT NULL,`telephone` char(11) DEFAULT NULL,`wechat` varchar(15) DEFAULT NULL,`class_id` tinyint(3) unsigned zerofill DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `telephone` (`telephone`),UNIQUE KEY `wechat` (`wechat`),KEY `class_id` (`class_id`),CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`) #重点在这里
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)mysql> desc student;
+-----------+------------------------------+------+-----+---------+----------------+
| Field     | Type                         | Null | Key | Default | Extra          |
+-----------+------------------------------+------+-----+---------+----------------+
| id        | int(3)                       | NO   | PRI | NULL    | auto_increment |
| name      | varchar(20)                  | NO   |     | NULL    |                |
| gender    | enum('男','女')              | YES  |     | NULL    |                |
| telephone | char(11)                     | YES  | UNI | NULL    |                |
| wechat    | varchar(15)                  | YES  | UNI | NULL    |                |
| class_id  | tinyint(3) unsigned zerofill | YES  | MUL | NULL    |                |
+-----------+------------------------------+------+-----+---------+----------------+

实际场景中,学生的信息在student表中存储,由于学生必然从属于某个班级,因此还需要存储学生班级的信息,由于多个学生可能共属于同一个班级,如果直接在student表中增加班级属性的列(如班级编号、班级类型等),会使student表的数据冗余。因此可以用另一个表class存储班级信息,再将class表作为主表,student表作为从表,建立外键联系。student表的class_id指的是学生的班级id,而这个class_id与class表的字段id建立了外键联系,这样在student表中,每个学生只需要存储一个class_id,就可以到class表中找到对应的班级信息,减少数据冗余。

试着向两个表插入一些数据!

mysql> select * from class;
+-----+-----------+
| id  | type      |
+-----+-----------+
| 001 | 普通班    |
| 002 | 实验班    |
+-----+-----------+
2 rows in set (0.00 sec)mysql> select * from student;
+----+--------+--------+-------------+--------+----------+
| id | name   | gender | telephone   | wechat | class_id |
+----+--------+--------+-------------+--------+----------+
|  1 | 张伟   || 12345678910 | 5555   |      001 |
|  2 | 一菲   || 11233113344 | 6666  |      002 |
+----+--------+--------+-------------+--------+----------+
6 rows in set (0.00 sec)

如果向student表中插入在class表中不存在的class_id,MySQL会拦截

mysql> insert into student (name, gender, telephone, wechat, class_id) values ('小贤','男',11111111222,7777, 3);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`ckf_d3`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))

如果从class表中删除了在student中已经存在的class_id,MySQL也不允许这样做

mysql> delete from class where id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`ckf_d3`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))

建立外键约束的本质其实就是把表与表之间逻辑上的相关性交给mysql去审核了,提前告诉mysql表之间的约束关系,那么当用户插入不符合业务逻辑的数据的时候,mysql不允许你插入!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/221590.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

获取Java类路径

利用System.getProperty(“java.class.path”)可以获取Java类路径(Java class path)。 package com.thb;import java.io.IOException;public class Test5 {public static void main(String[] args) throws IOException {System.out.println(System.getP…

【活动回顾】Databend 云数仓与 Databend Playground 扩展组件介绍

2023 年 12 月 7 日,作为 KubeSphere 的合作伙伴,Databend 荣幸地受邀参与了 KubeSphere 社区主办的云原生技术直播活动。本次活动的核心议题为「Databend 云数仓与 Databend Playground 扩展组件介绍」,此次分享由 Databend Labs 的研发工程…

大数据笔记(待续)

mysql 缓存技术 数据库和缓存双写数据一致性问题常见的解决方案 常见方案通常情况下,我们使用缓存的主要目的是为了提升查询的性能。大多数情况下,我们是这样使用缓存的: 用户请求过来之后,先查缓存有没有数据,如果有…

getResource()方法的使用以及路径问题

getResource()方法是Class类中的一个获取文件的方法,我在使用该方法稍微不注意经常会出现如下报错 Exception in thread "main" java.lang.NullPointerException 因此我觉得还是有必要写一篇博客来梳理以下该方法的误区、盲点。 首先getResource()方法可…

基于SSM的便民自行车管理系统

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

人工智能与VR技术

人工智能与虚拟现实技术(VR)的结合是当今科技领域中备受瞩目的话题。两者的结合不仅在娱乐、教育、医疗等领域展现出了巨大的潜力,而且在未来的发展趋势中也将具有重要意义。本文将从技术融合、应用场景和未来发展等方面探讨人工智能与虚拟现…

基于JAVA+SpringBoot+微信小程序的宠物领养平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: 随着人们生活水平的提…

系列十五、Redis面试题集锦

一、Redis面试题集锦 1.1、Redis到底是单线程还是多线程 Redis6.0版本之前的单线程指的是其网络IO和键值对读写是由一个线程完成的; Redis6.0引入的多线程指的是网络请求过程采用了多线程,而键值对读写命令仍然是单线程的,所以多线程环境下&…

Leetcode.75 颜色分类【荷兰国旗问题】

荷兰国旗问题 荷兰国旗问题是一个经典的计算机科学问题,它来源于荷兰国旗的颜色分布,荷兰国旗自上而下由红、白、蓝三个水平条组成。在算法领域,这个问题通常用于描述一种分类问题,其中元素只有三种类型(通常用三种颜…

多模态融合slam技术学习

目录 前言 一、视觉-惯性SLAM算法 二、激光-惯性SLAM算法 三、激光与视觉融合算法 总结 前言 最近在找实习,又想着要怎么完成毕业论文,打算做下机器人导航实验,学习下相关算法。今天是多模态融合slam技术,课程链接:h…

HarmonyOS(ArkTS)基础组件参数 媒体类型讲解

我们这里做了一个空的容器 然后 我们可以这样写 Entry Component struct Index {build() {Row() {Column() {Text("你好")Divider()Button("点击")}.width(100%)}.height(100%)} }这里 我们分别使用了三个组件 Text文本组件 Divider分割线组件 Button按钮…

c语言:指针运算

目录 指针类型与整型进行加减 规律 同类型指针减法运算 其他类型的指针运算 一个数据对象的内存位置有两个重要信息: 数据对象的首地址。数据对象占用存储空间大小 指针类型的值存储的是内存地址。内存地址是从0开始,依次加1的整型数据。 指针类…

echarts自定义tooltip位置和内容

tooltip: {trigger: item,backgroundColor: none,position: function (pos, params, dom, rect, size) {//我这个是每次显示30条数据 所以这么判断var obj params.dataIndex < 15 ? "right" : "left"return obj;},formatter: (params) > {//收入和…

第22关 深入解析K8s中的RBAC角色访问控制策略

------> 课程视频同步分享在今日头条和B站 大家好&#xff0c;我是博哥爱运维&#xff0c;在k8s上我们如何控制访问权限呢&#xff0c;答案就是Role-based access control (RBAC) - 基于角色&#xff08;Role&#xff09;的访问控制&#xff0c;&#xff08;RBAC&#xff0…

拥有「中美韩」资方背景的Story,下轮牛市密码?

Story由 (A16Z) 领投&#xff0c;帕丽斯希尔顿 (Paris Hilton) 提供 5400 万美元融资&#xff0c;标志着IP领域的一个转折点。他们认为 Story Protocol 有何独特之处&#xff1f;该项目旨在如何彻底改变数字世界&#xff1f;区块链的致富效应&#xff0c;已经让传统金融蠢蠢欲动…

大数据----31.hbase安装启动

二.Hbase安装 先前安装&#xff1a; Zookeeper 正常部署 首先保证 Zookeeper 集群的正常部署&#xff0c;并启动之。 三台机器都执行&#xff1a;zkServer.sh startHadoop 正常部署 Hadoop 集群的正常部署并启动。 主节点上进行 &#xff1a;start-all.sh 1.HBase 的获取 一定…

2023微博AIGC算法工程师一面 面试题

来源&#xff1a;投稿 作者&#xff1a;LSC 编辑&#xff1a;学姐 一面 35min左右&#xff0c;主要是根据简历发问的 1.自我介绍 介绍实习项目, 聊的比较详细&#xff0c;但是我实习项目限制比较多&#xff0c;做的不够深入。 2.多标签分类的损失函数 多标签分类任务&#x…

拦截器与过滤器的区别

1.最通俗的理解 过滤器&#xff1a;你要从一堆请求中通过一个工具挑选出符合你要求的请求&#xff0c;而这个工具就是过滤器 拦截器&#xff1a;当一个流程正在进行时&#xff0c;你希望干预它的进展&#xff0c;甚至是直接将它终止 2.触发时机不同 过滤器是在请求进入容器…

【数据结构/C++】二分查找

二分查找&#xff1a;根据索引二分&#xff0c;循环查找的条件是左索引小于等于右索引。 二叉树需要判断自身根是否为NULL&#xff0c;并通过改变current的值进行判断。 #include <iostream> using namespace std; // 长度为 N 的有序表nums 中查找 target int BiSearc…

14.Spring2.7.x 整合 Elasticsearch7.17

Elasticsearch&#xff1a;一个分布式的、Restful 风格的搜索引擎&#xff1b;支持对各种类型的数据的索引&#xff1b;搜索速度快&#xff0c;可以提供实时的搜索服务&#xff1b;便于水平扩展&#xff0c;每秒可以处理 PB 级海量数据 目录 1.Spring 整合 Elasticsearch 1.1…