开发者

MySql两表关联更新update示例SQL语句(用一个表更新另一个表)

开发者 https://www.devze.com 2025-06-28 08:59 出处:网络 作者: 我来整一篇
目录前言表及数据需求创建触发器关联无匹配,保持原数据正常情况:city表的code唯一异常情况:city表的code不唯一关联无匹配,清空原数www.devze.com据正常情况:city表的code唯一异常情况:city表的code不唯一结论未
目录
  • 前言
  • 表及数据
  • 需求
  • 创建触发器
  • 关联无匹配,保持原数据
    • 正常情况:city表的code唯一
    • 异常情况:city表的code不唯一
  • 关联无匹配,清空原数www.devze.com
    • 正常情况:city表的code唯一
    • 异常情况:city表的code不唯一
  • 结论
    • 未匹配,保留原有数据
    • 未匹配,清空原有数据
  • 总结 

    前言

    本文介绍了如何通过SQL语句实现两个表之间的关联更新,具体涉及city表和people表。city表包含城市代码和名称,people表包含人员信息及其所在城市的代码和名称。需求是根据city表更新people表中的城市名称。文章提供了两种更新方式:一种是在未匹配到关联数据时保留原有数据,另一种是未匹配时清空原有数据。此外,还介绍了如何通过触发器记录更新操作,并创建了审计表people_audit来存储更新js前后的数据。文章通过示例SQL语句展示了不同情况下的更新效果,并总结了更新时的注意事项。

    两表关联更新update (用一个表更新另一个表)

    表及数据

    • 建表及数据SQL

      SET NAMES utf8mb4;
      SET FOREIGN_KEY_CHECKS = 0;
      
      -- ----------------------------
      -- Table structure for city
      -- ----------------------------
      DROP TABLE IF EXISTS `city`;
      CREATE TABLE `city`  (
        `code` varchar(3) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
        `name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL
      ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
      
      -- ----------------------------
      -- Records of city
      -- ----------------------------
      INSERT INTO `city` VALUES ('001', '北京');
      INSERT INTO `city` VALUES ('002', '上海');
      INSERT INTO `city` VALUES ('003', '深圳');
      INSERT INTO `city` VALUES ('004', '南京');
      INSERT INTO `city` VALUES ('005', '广州');
      INSERT INTO `city` VALUES ('006', '成都');
      INSERT INTO `city` VALUES ('007', '重庆');
      
      SET FOREIGN_KEY_CHECKS = 1;
       
      SET NAMES utf8mb4;
      SET FOREIGN_KEY_CHECKS = 0;
      
      -- ----------------------------
      -- Table structure for people
      -- ----------------------------
      DROP TABLE IF EXISTS `people`;
      CREATE TABLE `people`  (
        `pp_id` int NULL DEFAULT NULL,
        `pp_name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
        `city_code` varchar(3) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
        `city_name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL
      ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
      
      -- ----------------------------
      -- Records of people
      -- ----------------------------
      INSERT INTO `people` VALUES (1, 'john', '001', '北京');
      INSERT INTO `people` VALUES (2, 'timo', '002', '');
      INSERT INTO `people` VALUES (3, '张三', '003', '合肥');
      INSERT INTO `people` VALUES (4, '李四', '008', '');
      INSERT INTO `people` VALUES (5, '王二麻', '009', '黑龙江');
      
      SET FOREIGN_KEY_CHECKS = 1;
      

    city表

    codename
    1北京
    2上海
    3深圳
    4南京
    5广州
    6成都
    7重庆

    people表

    pp_idpp_namecity_codecity_name
    1john1北京
    2timo2
    3张三3合肥
    4李四8
    5王二麻9黑龙江

    需求

    根据city表的code和name,更新people的city_name。

    创建触发器

    为了方便查看更新了那些行数据,为people表创建触发器

    先创建记录people更新记录的审计表

    CREATE TABLE `people_audit` (
      `id` int DEFAULT NULL,
      `old_value` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL,
      `new_value` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL,
      `updated_at` datetime DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
    

    创建每一行更新后触发器

    CREATE TRIGGER before_update_people
    BEFORE UPDATE ON people
    FOR EACH ROW
    BEGIN
      INSERT INTO people_audit(id, old_value, new_value, updated_at)
      VALUES(OLD.pp_id, OLD.city_name, NEW.city_namewww.devze.com, NOW());
    END;
    

    关联无匹配,保持原数据

    UPDATE people p , city c
    SET p.ci编程客栈ty_name = c.name 
    WHERE p.city_code = c.code 
    

    正常情况:city表的code唯一

    执行上面sql,输出:

    idold_valuenew_valueupdated_at
    1北京北京2024-5-13 10:19
    2上海2024-5-13 10:19
    3合肥深圳2024-5-13 10:19

    数据修改了三行,结论

    • 代码对应的城市更新,对应错误的更正
    • city表中没有的城市,在people表里保持原数据,不会被清空

    异常情况:city表的code不唯一

    插入一个重复code的数据

    insert into city values('003','合肥');
    

    恢复people表到初始数据,再次执行上面的更新sql,可以发现与上面返回值一致。

    推论:只取先匹配的一个值替换

    关联无匹配,清空原数据

    update people 
    set city_name = (
                    select min(name) -- 重复时匹配其中一个
                    from city
                    where code = people.city_code)
    

    或者

    UPDATE people p 
    LEFT JOIN city c ON p.city_code=c.`code`
    SET p.city_name = c.`name`
    

    正常情况:city表的code唯一

    idold_valuenew_valueupdated_at
    1北京北京2024-5-13 10:26
    2上海2024-5-13 10:26
    3合肥深圳2024-5-13 10:26
    42024-5-13 10:26
    5黑龙江2024-5-13 10:26

    数据修改了5行,结论

    • 代码对应的城市更新,对应错误的更正
    • city表中没有的城市,在people表里全被更新为null

    异常情况:city表的code不唯一

    不会报错,会选匹配其中一个更新。

    结论

    更新时未匹配到关联数据

    未匹配,保留原有数据

    UPDATE people p , city c  -- 两张表
    SET p.city_name = c.name   -- 更新值
    WHERE p.city_code = c.code -- 条件
    

    未匹配,清空原有数据

    update people 
    set city_name = (
                    select min(name) -- 重复时匹配其中一个
                    from city
                    where code = people.city_code)  
    

    或者

    UPDATE people p -- 要更新的表
    LEFT JOIN city c ON p.city_code=c.`code` -- 关联取数据的表
    SET p.city_name = c.`name` --更新表字段

    总结 

    到此这篇关于mysql两表关联更新update示例SQL语句的文章php就介绍到这了,更多相关MySql两表关联更新update内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号