1. 问题背景
在对项目代码的数据访问层接口进行单元测试时,发现了一个表中无数据(开发和测试库均为),另外对应的 mapper.xml
中无任何 SQL
语句,基本判定为无用代码,经过与开发负责人沟通确认,这些无用代码是当初为了迎合业务提前开发的,后面那个需求终止了,代码没有及时清理,遗留下来的废弃代码。故主动请缨计划临近版本优化删除该表及其 DAO 层代码。
2. 问题分析
该数据源类型为 Oracle
,当时建表的 DDL 语句中,新建了 表
、注释
、索引
、主键约束
、授权
和 同义词
。因此删除表的时候,其实就是一个 逆向过程
。表
+ 注释
+ 索引
+ 主键约束
+ 授权
,这些随着表删除后,烟消云散。但是 同义词
并不会,需要额外删除。
综上所述,需要删除 表
+ 同义词
。
为了实现表存在时才删除这样可以 重复执行
的 DDL
,由于 Oracle
不像 MySQL
那样有个判断子句 DROP TABLE #{表名} IF EXISTS;
,需要借助 存储过程
来实现。
3. 问题解决
BEGIN
EXECUTE IMMEDIATE 'drop table ' || 'TABLE_NAME' || ' purge'; -- 删除表
EXECUTE IMMEDIATE 'drop public synonym ' || 'TABLE_NAME'; -- 删除同义词
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
/ -- 标志结束
特别注意:
(1) 上述临时存储过程中,拼接 SQL 语句的时候,关键字和标识符仍需要保持空格;
(2) 最后的斜杠(/)不可以省略,表明结束;
(3) 上述执行成功的核心思路:抓住异常:如果不存在的话,还一意孤行去删除该表及其同义词的话,Oracle 就会抛出 -942 错误异常,我们将其抓住即可;
(4) 另外 purge 表明彻底删除,不支持回滚。