Oracle拉链表

什么是拉链表?

简单点说:记录一个事物,从开始一直到当前状态的所有变化信息。

复杂点说:记录数据在某一时间内的状态,以及数据在某一时间点的变化的数据存储方式。

为什么需要拉链表?

针对一些数据量大的表,像是保存了几年的数据,但是新增或者需要操作查看的数据只有一部分,或者只需要某个时间节点的数据,这个时候就可以使用拉链表进行操作。

怎么编写拉链表代码?

  1. 创建一个拷贝了emp的临时表emp1,防止修改到emp源表。
sql 复制代码
  	   drop table emp1;--如果以前有
       alter table emp1 add up_date date; --添加了一个新增数据的时间节点字段
       insert into emp1 e1(
          e1.empno,
          e1.ename,
          e1.job,
          e1.mgr,
          e1.hiredate,
          e1.sal,
          e1.comm,
          e1.deptno,
          e1.up_date
          )
          select 
          et.empno,
          et.ename,
          et.job,
          et.mgr,
          et.hiredate,
          et.sal,
          et.comm,
          et.deptno,
          sysdate-5
       from emp et;
       select * from emp1
  1. 创建目标表,用来比对emp1的数据
    重要字段start_date 、end_date 主要是这两个字段提取一段时间的数据。
sql 复制代码
---目标表
 drop table linkTable;
 create table linkTable as select * from emp where 1=2;
 select * from linkTable;
 alter table linkTable add up_date date;
 alter table linkTable add start_date date;--开始时间
 alter table linkTable add end_date date;--结束时间
 
 insert into linkTable lt(
        lt.empno,
        lt.ename,
        lt.job,
        lt.mgr,
        lt.hiredate,
        lt.sal,
        lt.comm,
        lt.deptno,
        lt.up_date,
        lt.start_date,
        lt.end_date
       
 )
        select 
          et.empno,
          et.ename,
          et.job,
          et.mgr,
          et.hiredate,
          et.sal,
          et.comm,
          et.deptno,
          et.up_date,
          to_date('2024-4-26','YYYY-MM-DD'),
          to_date('9999-9-9','YYYY-DD-MM')
        from emp1 et;
        
  1. 手动模拟新增的emp1数据
sql 复制代码
 update emp1 set sal=sal+1000,up_date=sysdate where ename='SMITH';
 insert into emp1 values(9999,'张三','xingjiapo',7369,
 				  date'1998-06-01',3600,1000,10,sysdate-1);
 select * from emp1;
 
  1. 创建一个存储过程,封装更新数据的动作。
    开链:目标中没有改记录,新增插入该条记录并把结束时间改成无穷大。
    闭链:目标中存在该条记录,只是部分状态值不同,update该数据,并把end_date调整为当日时间。
sql 复制代码
 ---创建存储过程
        create or replace procedure updateLinkTable(startTime varchar2,endTime varchar2)
        is
        v_start date := to_date(startTime,'YYYY-MM-DD HH24:MI:SS');
        v_end date := to_date(endTime,'YYYY-MM-DD HH24:MI:SS');
        cursor update_cursor is --创建游标保存指定时间内需要比对的数据
        select * from emp1  
        where up_date>=v_start and up_date<=v_end; ---指定时间内的数据
        v_count number;
        begin 
          for i in update_cursor loop --目标表与源表比对,
            select count(1) into v_count from linkTable lk --找到当前的数据并且当前数据未过期
            where i.empno = lk.empno and lk.end_date=to_date('9999-9-9','YYYY-MM-DD');
            
            if v_count=1 then
               update linkTable lk set lk.end_date=trunc(sysdate-1) --把原先的数据更新为过期数据(历史数据) 也就是闭链
               where i.empno = lk.empno and lk.end_date=to_date('9999-9-9','YYYY-MM-DD');
               --添加当前已更新的业务变动数据,并更新end_date无穷大
               insert into linkTable lk(
                      lk.empno,
                      lk.ename,
                      lk.job,
                      lk.mgr,
                      lk.hiredate,
                      lk.sal,
                      lk.comm,
                      lk.deptno,
                      lk.up_date,
                      lk.start_date,
                      lk.end_date
               ) values(
                      i.empno,
                      i.ename,
                      i.job,
                      i.mgr,
                      i.hiredate,
                      i.sal,
                      i.comm,
                      i.deptno,
                      i.up_date,
                      trunc(sysdate),
                      to_date('9999-9-9','YYYY-MM-DD')
               );
               elsif v_count=0 then --没有匹配上说明当前数据是新增数据,直接插入进去即可 (更新end_date无穷大 开链)
                  insert into linkTable lk(
                      lk.empno,
                      lk.ename,
                      lk.job,
                      lk.mgr,
                      lk.hiredate,
                      lk.sal,
                      lk.comm,
                      lk.deptno,
                      lk.up_date,
                      lk.start_date,
                      lk.end_date
               ) values(
                      i.empno,
                      i.ename,
                      i.job,
                      i.mgr,
                      i.hiredate,
                      i.sal,
                      i.comm,
                      i.deptno,
                      i.up_date,
                      trunc(sysdate),
                      to_date('9999-9-9','YYYY-MM-DD')
               );
            end if;
          end loop;
            exception
              when others then
                dbms_output.put_line(sqlcode);
                dbms_output.put_line(sqlerrm);
        end;
        
        select * from linkTable;
        select * from emp1;
  1. 调用存储过程,更新指定时间数据。
sql 复制代码
 ---方法一 pl/sql调用
begin
updateLinkTable('2024-5-28  00:00:00','2024-5-29 23:59:59');
end;
--方法二 SQL语句调用
call updateLinkTable(p_star => '2024-05-28 00:00:00',p_end => '2024-05-29 23:59:59');
-- 或者
call updateLinkTable('2024-05-28 00:00:00','2024-05-29 23:59:59');

拉链表的优缺点

优点

  • 节省存储空间,避免没必要的重复数据
  • 能查询到历史快照

缺点

  • 内存占用,查询效率受拉链长度的影响
  • 断链难以恢复
相关推荐
Francek Chen43 分钟前
【大数据存储与管理】分布式数据库HBase:03 HBase数据模型
大数据·数据库·hadoop·分布式·hdfs·hbase
小吴编程之路8 小时前
MySQL 索引核心特性深度解析:从底层原理到实操应用
数据库·mysql
~莫子8 小时前
MySQL集群技术
数据库·mysql
凤山老林8 小时前
SpringBoot 使用 H2 文本数据库构建轻量级应用
java·数据库·spring boot·后端
就不掉头发8 小时前
Linux与数据库进阶
数据库
与衫8 小时前
Gudu SQL Omni 技术深度解析
数据库·sql
咖啡の猫9 小时前
Redis桌面客户端
数据库·redis·缓存
oradh9 小时前
Oracle 11g数据库软件和数据库静默安装
数据库·oracle
what丶k9 小时前
如何保证 Redis 与 MySQL 数据一致性?后端必备实践指南
数据库·redis·mysql
_半夏曲9 小时前
PostgreSQL 13、14、15 区别
数据库·postgresql