Oracle - Flyway DB参考数据

时间:2017-05-29 15:27:26

标签: oracle deployment flyway

我正在研究在Oracle数据库中管理引用数据的最佳方法。我们将参考数据保存在源代码管理中,并在部署过程中更新参考表。

我们使用Flyway来部署我们的更改,并为每个参考表设置可重复的脚本,以确保每次部署后数据都是最新的。

在SQL Server数据库中,我们创建一个SQL脚本,其中包含insert语句到给定表的引用数据的变量表中,而不是使用MERGE语句来插入/更新/删除实际表。这样我们就可以管理每个分支的参考数据。

SQL Server示例

-- temporary table to hold all data
DECLARE @product_type TABLE
(
     [id] varchar(25)
    ,[name] varchar(50) 
)

INSERT @product_type ([id], [name]) VALUES ('1', 'Product 1')
INSERT @product_type ([id], [name]) VALUES ('2', 'Product 2')
INSERT @product_type ([id], [name]) VALUES ('3', 'Product 3')

-- merge changes into table
MERGE   [PRODUCT_TYPE] AS t
USING   @product_type AS s
ON      (t.[id] = s.[id])
WHEN    MATCHED
THEN    UPDATE 
        SET t.[name] = s.[name] 
WHEN    NOT MATCHED BY TARGET
THEN    INSERT  ([id], [name]) 
        VALUES  (s.[id], s.[name]);

--delete removed product type
DELETE [PRODUCT_TYPE] 
WHERE id NOT IN (SELECT id FROM @product_type)

因为在Oracle中你无法真正创建变量表甚至是短暂的临时表我不知道除了创建一个临时表然后在最后删除它之外,做什么是正确的方法。

Oracle Sample

BEGIN
   EXECUTE IMMEDIATE 'DROP TABLE TMP__product_type';
EXCEPTION
   WHEN OTHERS THEN
      IF SQLCODE != -942 THEN
         RAISE;
      END IF;
END;
/

CREATE TABLE TMP__product_type 
(
  id VARCHAR2(25 BYTE) NOT NULL 
, name VARCHAR2(50 BYTE) 
);


INSERT INTO TMP__product_type VALUES ('1,', 'Product 1');
INSERT INTO TMP__product_type VALUES ('2,', 'Product 2');
INSERT INTO TMP__product_type VALUES ('3,', 'Product 3');

MERGE INTO product_type T
   USING (SELECT id, name FROM TMP__product_type s) S
   ON (T.id = S.id)
   WHEN MATCHED THEN 
    UPDATE SET T.name = S.name
   WHEN NOT MATCHED THEN 
    INSERT (T.id, T.name)VALUES (S.id, S.name);

DELETE FROM product_type T WHERE NOT EXISTS (SELECT s.name FROM TMP__product_type s WHERE s.name = t.name);


BEGIN
   EXECUTE IMMEDIATE 'DROP TABLE TMP__product_type';
EXCEPTION
   WHEN OTHERS THEN
      IF SQLCODE != -942 THEN
         RAISE;
      END IF;
END;
/

欢迎任何建议。

1 个答案:

答案 0 :(得分:0)

将SQL Server方法转换为Oracle实际上非常简单。使用DUAL模仿内存表:

MERGE INTO product_type T
   USING (select '1' as id, 'Product 1' as name from dual union all
          select '2' as id, 'Product 2' as name from dual union all
          select '3' as id, 'Product 3'as name from dual ) S
   ON (T.id = S.id)
   WHEN MATCHED THEN 
    UPDATE SET T.name = S.name
   WHEN NOT MATCHED THEN 
    INSERT (T.id, T.name)VALUES (S.id, S.name);

这不处理DELETE。当然你知道自己的进程,但似乎处理这个问题的最佳方法是显式删除:

delete from product_type T
where T.id in ('4', '5');