加入Oracle闪回数据存档版本查询?

时间:2017-02-18 05:24:17

标签: database oracle join oracle11g flashback

我遇到的情况是,我试图基本上获取两个时间点之间数据集上发生的所有更改的列表。这似乎是Oracle中VERSIONS BETWEEN关键字的一个非常好的例子,但我不知道如何有效地加入其他表并获得我想要的结果。

我们说我有以下表格:

CREATE TABLE emp (
    emp_id        NUMBER(5) PRIMARY KEY,
    employee_name VARCHAR2(20)
    dept_id       NUMBER(3) NOT NULL
                     CONSTRAINT admin_dept_fkey REFERENCES dept
                     (dept_id))
);

CREATE TABLE dept(
    dept_id    NUMBER(5),
    department VARCHAR2(20)
);

如果员工记录发生变化,我需要能够获得员工记录更改时的部门名称,因为员工可能仍然属于同一部门而是部门名称在某些时候发生了变化。

实施例: EMP.VERSIONS_STARTSCN EMP_ID EMPLOYEE_NAME DEPT_ID部门 1 1 Michael 1服务 0 1迈克尔1销售

如果数据库被非规范化并且我将部门名称存储在表本身上,那将非常容易;但是,使用查找表似乎使它不那么直观。

我尝试过的事情:

SELECT *
FROM emp VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE e
JOIN dept d ON d.dept_id = e.dept_id;

这将使我成为今天存在的部门,但这并不能告诉我员工记录发生变化时的情况。

SELECT *
FROM emp VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE e
JOIN dept VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE d
ON d.dept_id = e.dept_id;

这也不好,因为它会返回多行,每个部门更换一个员工,其中我实际上只需要在员工记录更改时存在的部门

我也尝试了几个内部选择,但似乎Oracle不允许我在内部查询中使用VERSIONS_ENDSCN或VERSIONS_STARTTIME。我尝试过的变化包括:

SELECT 
    versions_startscn,
    e.employee_name,
    (SELECT department FROM dept AS OF SCN versions_startscn d WHERE d.dept_id = e.dept_id)
FROM emp VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE e

SELECT 
    e.employee_name
    (SELECT department FROM dept AS OF SCN versions_startscn d WHERE d.dept_id = e.dept_id)
FROM(
    SELECT 
        versions_startscn,
        e.employee_name,
    FROM emp VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE e
    )

这两个查询都会抛出一个未声明VERSIONS_STARTSCN的错误。

我觉得这必须是一个相当常见的用例,但我还没有找到任何使用VERSIONS BETWEEN加入的例子。我想出了一种方法来执行此操作,其中包括打开一个游标,员工更改BETWEEN SCN MINVALUE和MAXVALUE,将SCN选择为变量,然后从emp表和DEPT AS OF SCN中选择更改为嵌套表类型,但这似乎做了很多工作似乎相当简单。如果有人有任何想法,我将不胜感激。

我目前正在使用v11.2.0.4。

1 个答案:

答案 0 :(得分:0)

我的要求差不多

我只能通过检查一个表的版本时间是否在另一表的版本时间之间来考虑这样做。在其他表的开始和结束时间之间应该存在开始或结束时间,反之亦然。但这是非常昂贵且缓慢的。

nvl(tblB.versions_Endtime,tblB.versions_starttime) >=  tblA.versions_starttime and  nvl(tblB.versions_Endtime,tblB.versions_starttime) <=  nvl(tblA.versions_endtime, to_timestamp('9999-01-01 00:00:00','YYYY-MM-DD HH:MI:SS'))

OR

nvl(tblA.versions_Endtime,tblA.versions_starttime) >=  tblB.versions_starttime and 
nvl(tblA.versions_Endtime,tblA.versions_starttime) <=  nvl(tblB.versions_endtime, to_timestamp('9999-01-01 00:00:00','YYYY-MM-DD HH:MI:SS'))