深入 mysql,掌握一对一、一对多、多对多表设计、查询及级联操作

news2024/9/20 2:22:47

数据库表的基本概念与关系

数据库通常包含多个表,每个表存储特定类型的信息。例如:

  • 学生表:存储学生信息。
  • 老师表:存储老师信息。
  • 班级表:存储班级信息。

这些表通过各种关系连接,形成一个结构化的数据管理系统。主要的关系类型包括:

  • 一对多关系:如一个班级包含多名学生。
  • 多对多关系:如一个老师可教授多个班级,一个班级也可由多名老师教授。
  • 一对一关系:如一个用户对应一个身份证信息。

外键与表关联

外键是实现表之间关系的关键工具。通过外键,可以将两个表连接起来,实现数据的整合查询。

示例:用户表与身份证表的一对一关系:

  • 用户表(user):
    • id:主键,自动递增。
    • name:用户名,字符串类型。
  • 身份证表(id_card):
    • id:主键,自动递增。
    • card_name:身份证号,字符串类型。
    • user_id:外键,引用用户表的id。
 

sql

CREATE TABLE `user` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `id_card` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `card_name` VARCHAR(45) NOT NULL,
  `user_id` INT,
  PRIMARY KEY (`id`),
  INDEX `card_id_idx` (`user_id`),
  CONSTRAINT `user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
);

 

我们也可以选择可视化方式场景,选择 hello-mysql 数据库,点击建表按钮:
 

image.png


分别添加 id、name 列:
 

image.png


id_card 表:
 

image.png


指定外键 user_id 关联 user 表的 id:
 

image.png


还要选择主表数据 update 或者 delete 的时候,从表怎么办,这里我们先用默认的:

image.png

数据操作与查询

插入数据后,可以通过多表关联查询来查看关联数据:

 
-- 插入数据
INSERT INTO `user` (`name`)
	VALUES
		('张三'),
		('李四'),
		('王五');
INSERT INTO id_card (card_name, user_id) 
  VALUES
  ('110101199001011234',1),
	('310101199002022345',2),
	('440101199003033456',3);

-- 多表关联查询
-- 选择 user 表的 id 和 name 字段,以及 id_card 表的 id 和 card_name 字段
SELECT user.id, name, id_card.id AS card_id, card_name 
-- 从 user 表开始查询
FROM user
-- 与 id_card 表进行内连接,连接条件是 user 表的 id 字段等于 id_card 表的 user_id 字段
JOIN id_card ON user.id = id_card.user_id;


 

image.png


这就是多表关联查询,语法是 JOIN ON。

JOIN 类型解析

  • INNER JOIN(默认): 只返回两个表中能关联上的数据。
  • LEFT JOIN: 返回左表(FROM 语句之后的表)的所有记录,即使右表中没有匹配的记录。
  • RIGHT JOIN: 返回右表(JOIN 语句之后的表)的所有记录,即使左表中没有匹配的记录。

例如,使用 RIGHT JOIN 的查询如下:

-- 选择 user 表的 id 和 name 字段,以及 id_card 表的 id 和 card_name 字段
SELECT user.id, name, id_card.id AS card_id, card_name
-- 从 user 表开始查询
FROM user
-- 通过 RIGHT JOIN 右连接 id_card 表,连接条件是 user 表的 id 字段等于 id_card 表的 user_id 字段
RIGHT JOIN id_card ON user.id = id_card.user_id;

此查询将返回所有 id_card 的数据,对于没有关联的 user 数据,其对应字段会显示为 null
我们更新下 id_card 表的级联方式:
 

image.png


删除条 user 数据:
 

image.png


再执行上面的右查询代码:

image.png

外键约束与级联操作

外键约束用于维护数据库表之间的完整性。常见的外键约束处理方式包括:

  • RESTRICT / NO ACTION:(通常是默认行为) 只有当从表没有关联记录时,才允许删除或更新主表的记录。
  • CASCADE: 如果主表(外键指向的表)的记录被删除或更新,从表(有外键的表)的相应记录也会被级联删除或更新。
  • SET NULL: 如果主表的记录被删除或其关键字段被更新,从表的外键字段会被设置为 null

例如,如果设置外键约束为 CASCADE,并且更新了 user 表中某个 id,则 id_card 表中相应的 user_id 也会更新。如果删除了 user 表中的记录,所有关联的 id_card 记录也会被删除。

注意:在外键关系中,主表是被外键引用的表,而从表是包含外键的表。因此,当主表中的记录发生变更时,从表中依赖于这些记录的外键字段会受到影响。

一对多关系

一对多关系是数据库中常见的数据结构,其中一个实体可以关联多个其他实体,但这些被关联的实体仅指向单一实体。例如:

  • 作者与文章:一个作者可以写多篇文章,但每篇文章只能有一个作者。
  • 订单与商品:一个订单可以包含多个商品,但每个商品只属于一个订单。
  • 部门与员工:一个部门可以有多名员工,但每名员工只属于一个部门。

实现方式

在数据库中,通常通过在“多”的一方添加一个外键来实现一对多关系。
例如,员工表中会包含一个指向部门表的外键 department_id

 

 

-- 创建一个名为 `department` 的表,用于存储部门信息
CREATE TABLE `department` (
    `id` INT NOT NULL AUTO_INCREMENT,  -- 定义一个名为 `id` 的列,类型为 INT,不允许为空,自动增长
    `name` VARCHAR(45) NOT NULL,       -- 定义一个名为 `name` 的列,类型为 VARCHAR(45),不允许为空
    PRIMARY KEY (`id`)                 -- 将 `id` 列设置为主键
);

-- 创建一个名为 `employee` 的表,用于存储员工信息
CREATE TABLE `employee` (
    `id` INT NOT NULL AUTO_INCREMENT,  -- 定义一个名为 `id` 的列,类型为 INT,不允许为空,自动增长
    `name` VARCHAR(45) NOT NULL,       -- 定义一个名为 `name` 的列,类型为 VARCHAR(45),不允许为空
    `department_id` INT,               -- 定义一个名为 `department_id` 的列,类型为 INT,用于存储员工所属部门的 ID
    FOREIGN KEY (`department_id`) REFERENCES `department`(`id`) 
        ON DELETE SET NULL,            -- 设置外键,`department_id` 引用 `department` 表的 `id`,当部门被删除时,相关员工的 `department_id` 设置为 NULL
    PRIMARY KEY (`id`)                 -- 将 `id` 列设置为主键
);

创建了两个表:

  1. 部门表 (department)
    • id:部门的唯一标识符,自动增长,作为主键。
    • name:部门的名称,存储类型为长度最大为 45 的字符串。
  2. 员工表 (employee)
    • id:员工的唯一标识符,自动增长,作为主键。
    • name:员工的姓名,存储类型为长度最大为 45 的字符串。
    • department_id:外键,指向部门表的 id,表示员工所属的部门。如果所属部门被删除,员工记录中的 department_id 将被设置为 NULL,表示不再属于任何部门。

多对多关系

多对多关系指两种实体相互间可以有多个关联。例如:

  • 文章与标签:一篇文章可以有多个标签,同一个标签可以标记多篇文章。
  • 学生与课程:一个学生可以选修多门课程,一门课程可以被多个学生选修。
  • 用户与角色:一个用户可以拥有多个角色,一个角色可以包含多个用户。

实现方式

多对多关系通常通过一个中间表来实现,这个表存储两个实体之间的关联:

 

 

-- 创建一个名为 `article` 的表,用于存储文章信息
CREATE TABLE `article` (
    `id` INT NOT NULL AUTO_INCREMENT,  -- 定义一个名为 `id` 的列,类型为 INT,不允许为空,自动增长,用于唯一标识每篇文章
    `title` VARCHAR(50) NOT NULL,      -- 定义一个名为 `title` 的列,类型为 VARCHAR(50),不允许为空,用于存储文章的标题
    `content` TEXT NOT NULL,           -- 定义一个名为 `content` 的列,类型为 TEXT,不允许为空,用于存储文章的内容
    PRIMARY KEY (`id`)                 -- 将 `id` 列设置为主键
);

-- 创建一个名为 `tag` 的表,用于存储标签信息
CREATE TABLE `tag` (
    `id` INT NOT NULL AUTO_INCREMENT,  -- 定义一个名为 `id` 的列,类型为 INT,不允许为空,自动增长,用于唯一标识每个标签
    `name` VARCHAR(50) NOT NULL,       -- 定义一个名为 `name` 的列,类型为 VARCHAR(50),不允许为空,用于存储标签的名称
    PRIMARY KEY (`id`)                 -- 将 `id` 列设置为主键
);

-- 创建一个名为 `article_tag` 的中间表,用于存储文章和标签之间的多对多关系
CREATE TABLE `article_tag` (
    `article_id` INT NOT NULL,         -- 定义一个名为 `article_id` 的列,类型为 INT,不允许为空,用于引用文章表的 `id`
    `tag_id` INT NOT NULL,             -- 定义一个名为 `tag_id` 的列,类型为 INT,不允许为空,用于引用标签表的 `id`
    PRIMARY KEY (`article_id`, `tag_id`),  -- 将 `article_id` 和 `tag_id` 组合设置为主键,确保每对文章和标签的关系是唯一的
    FOREIGN KEY (`article_id`) REFERENCES `article`(`id`) ON DELETE CASCADE,  -- 设置外键,当引用的文章被删除时,相关的关联记录也会被自动删除
    FOREIGN KEY (`tag_id`) REFERENCES `tag`(`id`) ON DELETE CASCADE  -- 设置外键,当引用的标签被删除时,相关的关联记录也会被自动删除
);
  1. 文章表 (**article**)
    • id:文章的唯一标识符,自动增长,作为主键。
    • title:文章的标题,存储类型为长度最大为 50 的字符串。
    • content:文章的内容,存储类型为 TEXT,可以存储较长的文本。
  2. 标签表 (**tag**)
    • id:标签的唯一标识符,自动增长,作为主键。
    • name:标签的名称,存储类型为长度最大为 50 的字符串。
  3. 文章标签关联表 (**article_tag**)
    • article_idtag_id:用于存储文章和标签之间的关系。每个字段分别引用 article 表和 tag 表的 id
    • 通过设置复合主键(article_id, tag_id),确保每对文章和标签的关联是唯一的。
    • 外键约束带有 ON DELETE CASCADE 选项,意味着当删除文章或标签时,所有相关的关联记录也会自动被删除,这有助于维护数据库的完整性和一致性。

假设有以下文章和标签:

  • 文章1: ID = 1
  • 文章2: ID = 2
  • 标签A: ID = 1
  • 标签B: ID = 2
  • 标签C: ID = 3

文章到标签的关系如下:

  • 文章1 关联标签A 和 标签B
  • 文章2 关联标签A 和 标签C

那么 article_tag 表中的数据会是这样的:

 

 

+------------+--------+
| article_id | tag_id |
+------------+--------+
| 1          | 1      |
| 1          | 2      |
| 2          | 1      |
| 2          | 3      |
+------------+--------+

查询与操作

查询操作

使用 JOIN 语句可以查询出部门及其所有员工,或文章及其所有标签:

 

 

-- 查询部门及其员工
SELECT * 
FROM `department`  -- 从“department”表中选择数据,该表存储部门信息
JOIN `employee`    -- 通过 JOIN 操作与“employee”表连接
ON `department`.`id` = `employee`.`department_id`  -- 连接条件是部门表的 id 与员工表的部门 id 相匹配
WHERE `department`.`id` = 5;  -- 仅查询 id 为 5 的部门及其员工

-- 查询文章及其标签
SELECT `t`.`name` AS 标签名, `a`.`title` AS 文章标题
FROM `article` `a`  -- 从“article”表中选择数据,该表存储文章信息,并使用别名 `a`
JOIN `article_tag` `at` ON `a`.`id` = `at`.`article_id`  -- 通过 JOIN 操作连接“article_tag”表,使用别名 `at`,连接条件是文章 ID 匹配
JOIN `tag` `t` ON `t`.`id` = `at`.`tag_id`  -- 再通过 JOIN 操作连接“tag”表,使用别名 `t`,连接条件是标签 ID 匹配
WHERE `a`.`id` = 1;  -- 仅查询 id 为 1 的文章及其对应的标签

删除操作

删除一篇文章时,与之关联的标签关系也会被自动删除,这是通过设置外键的 ON DELETE CASCADE 选项实现的:

DELETE FROM `article` WHERE `id` = 1;
 

 

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

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

相关文章

vscode关闭git的提交提示

问题描述: vscode中光标停留在每一行都会有出现git仓库的提交信息,影响代码阅读。 解决方法: 左下角设置齿轮: 输入关键词commit input 取消勾选,即可解决。

判断n是否为两素数相乘

要求 请编写函数fun&#xff0c;其功能是:验证参数n是否可以分解成2个素数相乘&#xff0c;是则返回1&#xff0c;否则返回0&#xff0c;并通过指针变更x、y返回分解后的2个素数值&#xff0c;要求*x<*y。主程序中将打印出分解结果。 例如:1113*37&#xff0c;当函数fun的参…

Web APIs 第二天

第二天&#xff1a;DOM事件基础&#xff0c;注册事件&#xff0c;tab栏切换 添加事件监听 <body><button>点击</button><script>const btn document.querySelector(button)btn.addEventListener(click, function () {alert(嗲你)})</script> …

数据结构-3.3.栈的链式存储实现

一.链栈的定义&#xff1a; 二.总结&#xff1a;

Net8 调用BarTender2022 R8

先上效果图 官方只能支持.net framework&#xff0c;不支持.netCore 参考链接 https://support.seagullscientific.com/hc/en-us/community/posts/14770890037911-Support-for-NET-6 https://support.seagullscientific.com/hc/en-us/community/posts/360046932953-Make-SDK…

Web开发:ABP框架2——入门级别的增删改查Demo

目录 一、前言 二、上节回顾 ​编辑 三、新建Dto和添加映射 1.新建dto 2.添加映射规则 四、新建WebApi控制器用EFcore进行增删改查 1.新建Webapi控制器接口 2.新建Webapi控制器实现 3.跑项目测试 五、WebApi控制器调用底层代码 1.webapi控制器&#xff08;高层代码&…

JZ2440开发板——S3C2440的存储控制器

以下内容源于韦东山课程的学习与整理&#xff0c;如有侵权请告知删除。 课程中说的“内存控制器”&#xff0c;准确来说是“存储控制器”&#xff0c;其配套书籍写的也是“存储控制器”。 另外“Nor Flash控制器”&#xff0c;说的也是“存储控制器”&#xff0c;或者“存储控…

C++日期类,详细!!!

日期类的练习可以巩固提高之前所学习的知识&#xff0c;还可以完成关于的日期练习 下面是关于日期的对应oj题 KY111 日期差值 计算一年的第几天 累加天数 1.Date.h 头文件部分 看看我们要实现那些接口 1.获取对应月份的天数:GetMonthDay 2. < > …

pybind11 学习笔记

pybind11 学习笔记 0. 一个例子1. 官方文档1.1 Installing the Library1.1.1 Include as A Submodule1.1.2 Include with PyPI1.1.3 Include with Conda-forge 1.2 First Steps1.2.1 Separate Files1.2.2 PYBIND11_MODULE() 宏1.2.3 example.cpython-38-x86_64-linux-gnu.so 的…

轴承表面缺陷检测系统源码分享

轴承表面缺陷检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

GUI编程17:下拉框、列表框

视频链接&#xff1a;19、下拉框、列表框_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1DJ411B75F?p19&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.下拉框 代码示例 package com.yundait.lesson06;import javax.swing.*; import java.awt.*;public class Te…

Docker实践——天池篇

参考零基础入门Docker-cuda练习场_学习赛_天池大赛-阿里云天池的赛制 (aliyun.com) ​ 在Docker零基础入门-CSDN博客中我已经安装了docker,现在开始创建自己的镜像仓库。 1. 开通阿里云容器镜像服务(镜像仓库) 进入容器镜像服务 (aliyun.com) 1.1. 创建个人实例 点击“…

Vue | watch监听

Vue | watch监听 在Vue.js的世界里&#xff0c;watch监听器是一个强大且灵活的工具&#xff0c;它允许我们在数据变化时执行特定的逻辑。本文将深入探讨watch的出现背景、使用方法、应用场景、源码原理以及扩展技巧&#xff0c;旨在帮助读者全面掌握这一重要特性。 文章目录 Vu…

JavaEE---Spring IOC(2)

DI之三种注入 属性注入 构造方法注入 Setter注入 当程序中同一个类有多个对象的时候会报错解决方法如下: AutoWired和Resource的区别

C8T6--SPI读FLASH和双通信

C8T6–SPI读取FLASH和双通信 本小节以一种使用 SPI 通讯的串行 FLASH 存储芯片的读写实验为大家讲解 STM32 的 SPI 使用方法。实验中 STM32 的 SPI 外设采用主模式&#xff0c;通过查询事件的方式来确保正常通讯 大纲 SPI读取FLASH双SPI接口进行主从相互通信 具体案例 SPI…

SSC377/D, 5M30 64/128MB, 1Tops1. 支持双摄,甚至三摄;2. 夜视全彩;3. 省内存、省带宽;4. 算力较大,适合新的算法模型;

 High Performance Processor Core  ARM Cortex-A35  Clock rate up to 1.0 GHz  Neon and FPU  Memory Management Unit for Linux support  DMA Engine  Image/Video Processor  Supports 8/10/12-bit parallel interface for raw data inpu…

【算法基础实验】图论-BellmanFord最短路径

理论知识 Bellman-Ford 和 Dijkstra 是两种用于计算加权图中最短路径的算法&#xff0c;它们在多个方面存在不同之处。下面是它们之间的主要区别&#xff1a; 1. 边权重的处理 Bellman-Ford&#xff1a; 能够处理带有负权重边的图&#xff0c;且可以检测负权重环&#xff08…

chapter16-坦克大战【1】——(自定义泛型)——day21

目录 569-坦克大战介绍 570-JAVA坐标体系 571-绘图入门和机制 572-绘图方法 573-绘制坦克游戏区域 574-绘制坦克 575-小球移动案例 576-事件处理机制 569-坦克大战介绍 570-JAVA坐标体系 571-绘图入门和机制 572-绘图方法 573-绘制坦克游戏区域 574-绘制坦克 575-小球移…

硬件工程师笔试面试——保险丝

目录 10、保险丝 10.1 基础 保险丝原理图 保险丝实物图 10.1.1 概念 10.1.2 保险丝的工作原理 10.1.3 保险丝的主要类型 10.1.4 保险丝的选择和使用注意事项 10.2 相关问题 10.2.1 保险丝的额定电流和额定电压是如何确定的? 10.2.2 保险丝的熔断速度对电路保护有何…

二进制补码及与原码的互相转换方法-成都仪器定制

大沙把一些基础的知识说清楚&#xff0c;本文介绍二进制补码及与原码的转换方法。 先说原码&#xff0c;原码‌是一种计算机中对数字的二进制定点表示方法。在原码表示法中&#xff0c;数值前面增加了一位符号位&#xff0c;最高位为符号位&#xff0c;0表示正数&#xff0c;1表…