输出数据库全部表的外键引用拓扑结构

执行 sql:

SELECTconstraint_name,table_name,column_name,referenced_table_name,referenced_column_name
FROMinformation_schema.key_column_usage
WHEREtable_schema= '${databaseName}'
ANDreferenced_table_name IS NOT NULL

将执行结果复制到临时文件中:


blob_triggers_ibfk_1	blob_triggers		SCHED_NAME		triggers	SCHED_NAME
blob_triggers_ibfk_1	blob_triggers		TRIGGER_NAME	triggers	TRIGGER_NAME
blob_triggers_ibfk_1	blob_triggers		TRIGGER_GROUP	triggers	TRIGGER_GROUP
cron_triggers_ibfk_1	cron_triggers		SCHED_NAME		triggers	SCHED_NAME
cron_triggers_ibfk_1	cron_triggers		TRIGGER_NAME	triggers	TRIGGER_NAME
cron_triggers_ibfk_1	cron_triggers		TRIGGER_GROUP	triggers	TRIGGER_GROUP
simple_triggers_ibfk_1	simple_triggers		SCHED_NAME		triggers	SCHED_NAME
simple_triggers_ibfk_1	simple_triggers		TRIGGER_NAME	triggers	TRIGGER_NAME
simple_triggers_ibfk_1	simple_triggers		TRIGGER_GROUP	triggers	TRIGGER_GROUP
simprop_triggers_ibfk_1	simprop_triggers	SCHED_NAME		triggers	SCHED_NAME
simprop_triggers_ibfk_1	simprop_triggers	TRIGGER_NAME	triggers	TRIGGER_NAME
simprop_triggers_ibfk_1	simprop_triggers	TRIGGER_GROUP	triggers	TRIGGER_GROUP
triggers_ibfk_1			triggers			SCHED_NAME		job_details	SCHED_NAME
triggers_ibfk_1			triggers			JOB_NAME		job_details	JOB_NAME
triggers_ibfk_1			triggers			JOB_GROUP		job_details	JOB_GROUP

稍微处理下输出如下:

表 blob_triggers 外键引用了表 triggers
表 cron_triggers 外键引用了表 triggers
表 triggers 外键引用了表 job_details
表 simple_triggers 外键引用了表 triggers
表 simprop_triggers 外键引用了表 triggers

这种结构还是不够直观,没法一下子看出哪些表未被任何其他表外键引用( 只有删除或清空未被任何其他表外键引用的表的数据时,才不会提示“删除失败,该表已被表xxx 外键引用” ),那么该如何展示才够直观呢,才能一下子看出来哪些表未被其他任何表引用呢?我们想到了树结构,即父id自关联的树结构,比如公司的部门树结构,删除叶子节点不会提示被引用,而删除父节点会提示被引用,无法删除,所以我们应该把被外键引用的表作为树的父节点,把未被任何其他表外键引用的表作为叶子节点。

完整代码:

FKReferenceTopologyPrintTest.java:
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;public class FKReferenceTopologyPrintTest {public static void main(String[] args) {String filePath = "\\xxx\\...\\xxx_FKReferenceList.txt";List<RelationDirectionVO> relations = readFile2Relations( filePath );Map<String, TableNode> map_tableName_tableNode = new HashMap<>();for( RelationDirectionVO relation:relations ){// a 引用了 b 就表示 a 是 b 的孩子System.out.println( "表 [" + relation.getTableName_from() + "]" + " 外键引用了表 [" + relation.getTableName_to() + "]" );String tableNameTo = relation.getTableName_to();String tableNameFrom = relation.getTableName_from();TableNode tableNode_parent = map_tableName_tableNode.get(tableNameTo);if( tableNode_parent == null ){tableNode_parent = new TableNode();tableNode_parent.setTableName( tableNameTo );map_tableName_tableNode.put( tableNameTo,tableNode_parent );}TableNode tableNode_child= map_tableName_tableNode.get(tableNameFrom);if( tableNode_child == null ){tableNode_child = new TableNode();tableNode_child.setTableName( tableNameFrom );map_tableName_tableNode.put( tableNameFrom,tableNode_child );}// 设置 children 关系List<TableNode> children = tableNode_parent.getChildren();if( children == null ){children = new ArrayList<>();tableNode_parent.setChildren( children );}children.add( tableNode_child );//  设置 parent 关系List<TableNode> parents = tableNode_child.getParents();if( parents == null ){parents = new ArrayList<>();tableNode_child.setParents( parents );}parents.add( tableNode_parent );}System.out.println();System.out.println();// printSet<String> tableNames = map_tableName_tableNode.keySet();for( String tableName:tableNames ){TableNode tableNode = map_tableName_tableNode.get(tableName);List<TableNode> parents = tableNode.getParents();if( parents != null && parents.size() > 0 ){// 该节点 有 parent 节点,则不直接输出此节点了( 此节点必然会在输出其父节点时被打印出来 )continue;}printTableNode( "",tableNode );System.out.println();}}private static List<RelationDirectionVO> readFile2Relations(String filePath) {BufferedReader reader = null;try {reader = new BufferedReader(new FileReader(filePath));String line = reader.readLine();Map<String, TableNode> map_tableName_tableNode = new HashMap<>();Map<String, RelationDirectionVO> map_key_relation = new HashMap<>();while (line != null) {// System.out.println(line);String[] array = line.split("\\s+");String table_name = array[1];String referenced_table_name = array[3];String key = table_name + "--->" + referenced_table_name;if( map_key_relation.containsKey( key ) ){line = reader.readLine();continue;}RelationDirectionVO relation = new RelationDirectionVO();relation.setTableName_from( table_name );relation.setTableName_to( referenced_table_name );map_key_relation.put( key,relation );}List<RelationDirectionVO> relationList = new ArrayList<>();Set<String> keys = map_key_relation.keySet();for( String key:keys ){RelationDirectionVO relation = map_key_relation.get(key);relationList.add( relation );}return relationList;} catch (Exception e) {e.printStackTrace();return null;} finally {if (reader != null) {try {reader.close();} catch (Exception e) {e.printStackTrace();}}}}private static void printTableNode( String padding,TableNode tableNode) {if( tableNode == null ){return;}System.out.println( padding + "[" + tableNode.getTableName() + "]" );List<TableNode> children = tableNode.getChildren();if( children == null || children.size() == 0 ){return;}for( TableNode child:children ){printTableNode( padding + "\t",child );}return;}
}

RelationDirectionVO.java:
import lombok.Getter;
import lombok.Setter;import java.io.Serializable;@Getter
@Setter
public class RelationDirectionVO implements Serializable {private String tableName_from;private String tableName_to;}

TableNode.java:
import lombok.Getter;
import lombok.Setter;import java.util.List;@Getter
@Setter
public class TableNode {private String tableName;private List<TableNode> children;private List<TableNode> parents;
}

输出外检引用拓扑结构关系:

表 blob_triggers    外键引用了表 triggers
表 cron_triggers    外键引用了表 triggers
表 simple_triggers  外键引用了表 triggers
表 simprop_triggers 外键引用了表 triggers
表 triggers         外键引用了表 job_detailsjob_detailstriggersblob_triggerscron_triggerssimple_triggerssimprop_triggers

这样我们就知道叶子节点表示的是未被其他任何表外键引用的表了,可以直接删除或清理数据

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

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

相关文章

【Leetcode每日一刷】贪心算法|122.买卖股票的最佳时机 II、55. 跳跃游戏

一、122.买卖股票的最佳时机 II 力扣题目链接 &#x1f984;解题思路&#xff1a; 首先需要明确的几个点&#xff1a; 当前只能有最大一支股票每一天操作只能3选1&#xff1a;买or卖or休息 此外&#xff0c;对于贪心&#xff0c;总有像下面图示的一种直觉&#xff1a;如果…

力扣SQL50 产品销售分析 I 查询

Problem: 1068. 产品销售分析 I 思路 left join on&#xff1a;左连接 Code select p.product_name, s.year, s.price from Sales s left join Product p on s.product_id p.product_id

靠谱的车【华为OD机试-JAVAPythonC++JS】

题目描述 程序员小明打了一辆出租车去上班。出于职业敏感&#xff0c;他注意到这辆出租车的计费表有点问题&#xff0c;总是偏大。 出租车司机解释说他不喜欢数字4&#xff0c;所以改装了计费表&#xff0c;任何数字位置遇到数字4就直接跳过&#xff0c;其余功能都正常。 比如&…

Scaffold 脚手架

Scaffold 脚手架 Scaffold 脚手架组件是一个核心组件&#xff0c;它为开发者提供了一个标准的、可定制的应用界面框架。androidx.compose.material3.Scaffold 包含了应用界面的基础元素&#xff0c;如状态栏、导航栏、顶部应用栏&#xff08;TopAppBar&#xff09;等。通过 Sc…

Windows的Docker-Desktop安装与问题总结

目录 Docker-Desktop安装步骤 环境配置 Docker-Desktop安装问题总结 问题1&#xff1a;docker-desktop setting界面一直加载转圈 问题2&#xff1a;docker镜像的存储位置变更&#xff08;防止C盘空间不足&#xff09; 参考文献&#xff1a; Docker-Desktop安装步骤 环境…

又挖到宝了!国人团队研发的AI视频工具PixVerse,这么好用居然还完全免费!(强烈推荐)

昨天发了一款国产免费的 AI 绘画工具 Dreamina 的介绍&#xff1a; 居然才发现&#xff01;字节跳动旗下国产AI绘画工具Dreamina&#xff0c;这么好用居然还免费&#xff01;&#xff08;强烈推荐&#xff09; 发现大家对国产 AI 工具还挺感兴趣的。今天继续帮大家挖国产的 A…

【Leetcode每日一题】二分查找 - 山脉数组的峰顶索引(难度⭐⭐)(23)

1. 题目解析 Leetcode链接&#xff1a;852. 山脉数组的峰顶索引 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于找到题目中所说的峰值所在的下标并返回他们的下标即可。 2. 算法原理 峰顶及两侧数据特点分析 峰顶数据…

运算放大电路常用接法

1、反相比例运算电路 2、同相比例运算电路 3、电压跟随器 4、反相求和运算电路 5、同相求和运算电路 6、加减运算电路 7、加减电路 8、积分运算电路 9、实用积分电路 10、微分运算电路 11、实用微分电路 12、压控电压源二阶低通滤波器 13、压控电压源二阶高通滤波器 14、RC桥式…

[剪藏] - 尊湃通讯公司窃密曝光,发现绕不过华为

在科技领域风起云涌的今天&#xff0c;一场惊心动魄的窃密事件悄然发生&#xff0c;涉及华为WIFI6芯片技术的商业秘密被窃取&#xff0c;案中主谋竟然是一位曾在华为海思拥有重量级地位的技术大佬。本文将深入挖掘这起事件的来龙去脉&#xff0c;探讨窃密者的背叛和华为的技术守…

CDGA数据治理工程师模拟试题(文末附链接)

单选题&#xff0c;每题仅有一个正确的选项。(本题型共有100道,总计100分) 1、关于元数据管理原则说法正确的是 A.确保员工了解如何访问和使用元数据。 B.制定、实施和审核元数据标准&#xff0c;以简化元数据的集成和使用。 C.创建反馈机制&#xff0c;以便数据…

公钥密码体制

公钥密码体制 一个系统中,n个用户之间要进行保密通信,为了确保安全性,两两用户之间的密钥不能一样。这种方式下,需要系统提供C2 n=n(n-1)/2把共享密钥。这样密钥的数量就大幅增加了,随之而来的产生、存储、分配、管理密钥的成本也大幅增加。而使用公钥密码体制可以大大减…

超1000本计算机经典书籍分享(均可免费下载)

今天给大家推荐两个开源项目&#xff0c;均可百度网盘下载&#xff1a; 1 https://gitee.com/ForthEspada/CS-Books 超过1000本的计算机经典书籍、个人笔记资料以及作者在各平台发表文章中所涉及的资源等。 书籍资源包括C/C、Java、Python、Go语言、数据结构与算法、操作系统…

深度学习-回顾经典AlexNet网络:山高我为峰

深度学习-回顾经典AlexNet网络之山高我为峰 深度学习中&#xff0c;经典网络引领一波又一波的技术革命&#xff0c;从LetNet到当前最火的GPT所用的Transformer&#xff0c;它们把AI技术不断推向高潮。2012年AlexNet大放异彩&#xff0c;它把深度学习技术引领第一个高峰&#x…

总结一下linux性能检测和调优手段

1.perf 是 Linux 系统中性能分析工具&#xff0c;用于收集性能相关的信息。它可以用于查看 CPU 使用情况、内存性能、磁盘 I/O 等&#xff0c;以帮助开发者找到性能瓶颈。 以下是一些 perf 常见用法和示例&#xff1a; 1. CPU Profiling a. 查看 CPU 使用率 perf stat -e cpu…

10分钟SkyWalking与SpringBoot融合并整合到Linux中

1.依赖配置 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.2.0.RELEASE</version></dependency><dependency><groupId>org.springframe…

复试PAT乙级day33

PAT乙级1106~1110 1106_2019数列有一个测试点过不了 1109_擅长C 这题不会&#xff0c;通过的是别人的代码 1110_区块反转 这题跟1105_链表合并 的处理很像。值得注意的是分段区间翻转用 大转小转 的方式。这题也有一个测试点通不过。

从模型到复合AI系统的转变

2023年,大型语言模型(LLM)吸引了所有人的注意力,它可以通过提示来执行通用任务,例如翻译或编码。这自然导致人们将模型作为AI应用开发的主要成分而密切关注,所有人都在想新的LLM将带来什么能力。然而,随着越来越多的开发者开始使用LLM构建,我们认为这种关注正在迅速改变:最先进…

阿里云OSS挂到到ECS作为一个linux目录(OSSFS挂载)

配置OSS账号信息并挂载OSS Bucket。以下是该文档的示例&#xff1a; OSSFS 配置与挂载指南 步骤 1&#xff1a;安装必要的依赖包 首先&#xff0c;确保您的系统已经安装了wget和fuse。这些工具是下载OSSFS安装包和挂载文件系统所必需的。 bash复制代码 # 检查并安装 wget if…

数据服务安全的重要性

数据服务安全在当今信息化社会显得尤为重要。随着大数据、云计算、人工智能等技术的飞速发展&#xff0c;数据已经成为企业和组织的核心资产&#xff0c;数据服务安全也面临着前所未有的挑战。本文将从数据服务安全的重要性、常见威胁、防护策略以及未来发展趋势等方面进行探讨…

selenuim【1】($x(‘xpath语法’)、WebDriverWait())

文章目录 初学selenuim记录1、执行driver webdriver.Chrome()后很久才打开浏览器2、浏览器多元素定位 $x(‘xpath语法’)3、打开浏览器driver.get("网址")执行了很久才开始定位元素&#xff1a;等待&#xff08;1&#xff09;driver.set_page_load_timeout(t)&#…