【发布时间】:2018-04-11 14:52:25
【问题描述】:
我们有一个数据库迁移脚本,通过 FlyWay 运行,它是 Java 应用程序的一部分。问题是一些客户拥有旧版本的应用程序,其中显示了一些表格和数据,而其他客户将安装此产品作为新解决方案。这些脚本必须每次都运行(解决问题和历史问题)。
事实上,我们在 SQL 中通过简单的检查来处理这个问题,如果表存在,然后执行其余的脚本。它适用于其他数据库(Postgres、MySQL、MS SQL)但不适用于 Oracle。经过几天的尝试和谷歌搜索,我开始把头发从头上扯下来。第一个问题是执行 DDL 语句(已经知道我不能这样做),现在是这个。
我们训练的目标是什么:
- 如果当前用户存在主表,则运行脚本(这就是我们 确定,如果所有其他表也存在)
- 我们需要为每个表创建一个备份表并复制其中的所有行(这就是我们执行 TRUNCATE 和 INSERT INTO 的原因,如果失败, 我们做 CREATE TABLE AS) - 这是呈现的代码应该做的,IF table_count > 0 THEN 和 END IF 内的代码块;每个呈现的表格都会重复 (11x)
- 然后我们运行清理脚本,该脚本会检查错误数据并清理它们(我们必须存储原始值以防万一 坏了)。
- 清理后的数据被复制到新表中(在之前的脚本中准备)。
总共有 10 个脚本,但这个总是失败。
代码如下:
DECLARE
table_count NUMBER;
curr_user VARCHAR2(100);
BEGIN
SELECT
sys_context('USERENV','SESSION_USER') INTO curr_user
FROM dual;
SELECT count(*)
INTO table_count
FROM all_objects
WHERE object_type IN ('TABLE', 'VIEW')
AND object_name = 'main_table'
AND owner = curr_user;
IF table_count > 0 THEN
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE some_table_backup';
EXECUTE IMMEDIATE 'INSERT INTO some_table_backup
SELECT *
FROM some_table';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942
THEN
RAISE;
ELSE
EXECUTE IMMEDIATE 'CREATE TABLE some_table_backup AS SELECT * FROM some_table';
END IF;
END;
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE some_table_backup2';
EXECUTE IMMEDIATE 'INSERT INTO some_table_backup2
SELECT *
FROM some_table2';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942
THEN
RAISE;
ELSE
EXECUTE IMMEDIATE 'CREATE TABLE some_table_backup2 AS SELECT * FROM some_table2';
END IF;
END;
.
.
.
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line(SQLERRM);
END;
错误如下:
ORA-06550:第 30 行,第 8 列:
PLS-00103:在预期以下情况之一时遇到符号“文件结尾”:
第 30 行是 END;结束 IF 之后;在脚本的第一个分区中。
【问题讨论】: