惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
腾讯CDC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
K
Kaspersky official blog
V
Visual Studio Blog
博客园 - 聂微东
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog
C
Check Point Blog
H
Heimdal Security Blog
The GitHub Blog
The GitHub Blog
Google Online Security Blog
Google Online Security Blog
P
Proofpoint News Feed
AI
AI
The Register - Security
The Register - Security
SecWiki News
SecWiki News
Help Net Security
Help Net Security
T
Troy Hunt's Blog
V
V2EX
T
Tenable Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Forbes - Security
Forbes - Security
P
Privacy International News Feed
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
Recorded Future
Recorded Future
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 司徒正美
博客园 - 叶小钗
Y
Y Combinator Blog
人人都是产品经理
人人都是产品经理
S
Security @ Cisco Blogs
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
L
LINUX DO - 最新话题
V2EX - 技术
V2EX - 技术
The Cloudflare Blog
Jina AI
Jina AI
T
The Exploit Database - CXSecurity.com
L
Lohrmann on Cybersecurity
Webroot Blog
Webroot Blog
美团技术团队
N
News and Events Feed by Topic
小众软件
小众软件
Google DeepMind News
Google DeepMind News
G
GRAHAM CLULEY
阮一峰的网络日志
阮一峰的网络日志
B
Blog

博客园 - dirgo

logback-spring.xml引入了base.xml日志文件默认生成在哪里? application.yml中Logback相关配置 org/springframework/boot/logging/logback/defaults.xml的内容和作用 logback-spring.xml 中<include resource="org/springframework/boot/logging/logback/base.xml"/>作用 Spring Boot 项目 Logback 日志框架配置文件logback-spring.xml详解 Oracle DataBaseLink 提示密码过期 梅特勒托-托利多衡器串口连续输出数据格式的说明 utf-8编码详解 mybaits updateWrapper更新报错:无效的列类型: 1111 @RequestPart和@RequestParam有什么区别 如何避免Mass Assignment漏洞? 关于vxe-table v4 导出大数据量excel浏览器卡死问题的解决 开源的Linux换源和安装docker脚本 wsl常用命令 使用网页静默打印 在Oracle中,授予用户角色和权限 Linux下查看当前哪些端口在监听状态,哪些端口在连接状态 mobaxterm常用配置 Windows下udp工具 Oracle表空间用户授权创建dblink等操作 用nmap扫描找出某个网段下空闲的ip脚本 Oracle 19c 常用运维 SQL Linux下设置CDB/PDB 环境的Oracle19c开机启动 Oracle是 CDB/PDB 环境下,让PDB在数据库启动后自动打开 怎样禁止dbeaver点击导航中数据库自动切换sql编辑器所属的数据库 Oracle 19c占内存高的解决方法 sudo -i -u zhangsan 与su - zhangsan区别,在现代 Linux 系统中,推荐使用 sudo 进行权限切换 Linux 的目录结构英文全称(及可能的命名背景)和更详细的说明 利用 Logback 的热加载特性,安全的迁移日志,改变日志保存路径 Linux中查询进程内存占用 iotDB调整内存占用及注意事项 Eclipse Milo 处理PLC&quot;字(Word)&quot;类型,最直接和正确的做法是使用其内置的 UShort 类型 centos7.9安装minio RELEASE.2025-04-22T22-12-26Z centos7.9编译安装nginx 1.28.1 linux(centos7.9)编译安装redis7.2.4 UFW 防火墙常用命令速查表
Oracle关联表删除数据和更新数据
dirgo · 2026-07-24 · via 博客园 - dirgo

[AI生成]

一.关联删除

通常建议使用 EXISTS 方式,因为这种方式在处理多表关联删除时逻辑最清晰,且性能较稳定。
假设关联模型是:table1 -> table2 -> table3(即 table1 关联 table2,table2 关联 table3)。
以下是几种常用写法:

方法一:使用 EXISTS 子查询(推荐)

这种方式最通用。你只需要在子查询中把 table2table3 关联起来,然后让 table1 去匹配这个结果。

DELETE FROM table1 t1
WHERE EXISTS (
    SELECT 1
    FROM table2 t2
    JOIN table3 t3 ON t2.id = t3.t2_id  -- table2 和 table3 的关联条件
    WHERE t1.id = t2.t1_id              -- table1 和 table2 的关联条件
      AND t3.status = 'INVALID'         -- table3 的过滤条件(可选)
);

逻辑解释:

  1. 子查询内部 (FROM table2 JOIN table3 ...) 先把 table2 和 table3 按照条件关联好。
  2. 外层的 WHERE t1.id = t2.t1_id 表示 table1 需要在这个关联结果中存在。
  3. 只要子查询能查到数据,EXISTS 就返回 true,DELETE 就会执行。

方法二:使用 IN 子查询

如果你是通过某个具体字段(比如ID)来筛选,可以使用 IN。这种方式是先查出所有符合条件的 ID,再删除。

DELETE FROM table1
WHERE id IN (
    SELECT t2.t1_id
    FROM table2 t2
    JOIN table3 t3 ON t2.id = t3.t2_id
    WHERE t3.status = 'INVALID'
);

方法三:使用内联视图删除

Oracle 支持删除带有关联的视图,前提是 table1 的关联字段必须是主键。

DELETE FROM (
    SELECT t1.*
    FROM table1 t1
    JOIN table2 t2 ON t1.id = t2.t1_id
    JOIN table3 t3 ON t2.id = t3.t2_id
    WHERE t3.status = 'INVALID'
);

注意: 这种写法虽然简洁,但如果 table1.id 不是主键,或者 Oracle 无法确定 table1 是“键值保留表”,执行时会报错 ORA-01752。因此,方法一(EXISTS)通常是最稳妥的选择

总结

不论你需要关联多少张表,核心思路都是:

  1. 先写一个 SELECT 查询,把 table1table2table3所有需要的表关联起来,并加上过滤条件。
  2. 把这个查询作为子查询,放入 DELETE FROM table1 WHERE EXISTS (子查询) 中,并加上 table1 与子查询表的关联条件。

二. 关联更新

2.1 更新字段为固定值

有几种常见的写法。考虑到不同的数据库(如 Oracle, MySQL, SQL Server, 达梦等)语法略有差异,我为您提供两种最常用且兼容性最好的写法:

方法一:使用 EXISTS(推荐,兼容几乎所有关系型数据库)

这种写法最稳妥,通过子查询判断是否符合关联条件。

UPDATE AUTO_SAMPLE.SAMPLE_PLAN sp
SET sp.VALIDFLAG = -1
WHERE sp.VALIDFLAG > 0 
  AND sp.SAMPLED_COUNT IS NULL 
  AND sp.SAMPLE_STATUS = 1
  AND EXISTS (
      SELECT 1 
      FROM MFIS_USER.HG_TASK ht 
      WHERE ht.TASKID = sp.TASKID 
        AND ht.VALIDFLAG = 3
  );

方法二:使用 MERGE INTO(适用于 Oracle, 达梦等数据库)

如果您的数据库是 Oracle 或国产达梦等,使用 MERGE 语法在性能和可读性上也非常好。

MERGE INTO AUTO_SAMPLE.SAMPLE_PLAN sp
USING MFIS_USER.HG_TASK ht
ON (sp.TASKID = ht.TASKID)
WHEN MATCHED THEN 
    UPDATE SET sp.VALIDFLAG = -1
    WHERE sp.VALIDFLAG > 0 
      AND sp.SAMPLED_COUNT IS NULL 
      AND ht.VALIDFLAG = 3 
      AND sp.SAMPLE_STATUS = 1;

注意事项:

在执行 UPDATE 之前,建议您先用事务包裹,或者在执行前用原 SELECT 语句确认一下数据量,执行后确认无误再 COMMIT

2.2更新字段值为关联表的某个字段值

要实现“根据 B 表的数据更新 A 表”的需求,不同的数据库有不同的标准写法。以下提供三种最常见的改写方法,您可以根据您使用的数据库类型(如 Oracle、MySQL、SQL Server、达梦等)选择合适的一种:

方法一:使用 MERGE INTO(强烈推荐:适用于 Oracle, 达梦, SQL Server, DB2 等)

MERGE INTO 是专门用来做“存在则更新”的操作,语法清晰且执行效率高。

MERGE INTO AUTO_SAMPLE.SAMPLE_PLAN sp
USING MFIS_USER.HG_TASK ht
ON (sp.TASKID = ht.TASKID AND ht.VALIDFLAG > 0)
WHEN MATCHED THEN 
    UPDATE SET sp.TARGETNAME = ht.TARGETNAME
    WHERE sp.VALIDFLAG > 0 
      AND sp.TARGETNAME IS NULL;

方法二:使用 UPDATE ... JOIN(适用于 MySQL, SQL Server)

如果你的数据库是 MySQL 或 SQL Server,可以直接在 UPDATE 语句中使用 JOIN

UPDATE AUTO_SAMPLE.SAMPLE_PLAN sp
JOIN MFIS_USER.HG_TASK ht ON sp.TASKID = ht.TASKID AND ht.VALIDFLAG > 0
SET sp.TARGETNAME = ht.TARGETNAME
WHERE sp.VALIDFLAG > 0 
  AND sp.TARGETNAME IS NULL;

方法三:使用标量子查询(适用于几乎所有数据库,包括 Oracle 和 MySQL)

如果不使用 JOIN,可以在 SET 中使用子查询直接取出对应的值。这种写法兼容性最好,但要注意:如果子查询返回多行会报错,因此加了过滤条件确保只返回一行。

UPDATE AUTO_SAMPLE.SAMPLE_PLAN sp
SET sp.TARGETNAME = (
    SELECT ht.TARGETNAME 
    FROM MFIS_USER.HG_TASK ht 
    WHERE ht.TASKID = sp.TASKID 
      AND ht.VALIDFLAG > 0
      -- 如果是 Oracle/达梦,可以加 ROWNUM = 1 防止多行报错
      -- 如果是 MySQL,可以加 LIMIT 1
)
WHERE sp.VALIDFLAG > 0 
  AND sp.TARGETNAME IS NULL 
  AND EXISTS (
      SELECT 1 
      FROM MFIS_USER.HG_TASK ht 
      WHERE ht.TASKID = sp.TASKID 
        AND ht.VALIDFLAG > 0
  );

总结建议
如果您使用的是 Oracle 或 达梦 数据库,请优先使用 方法一;如果您使用的是 MySQL,请优先使用 方法二