如何根据要删除的行调整其他行数据

时间:2015-05-18 17:06:29

标签: sql database plsql relational-database plsqldeveloper

我有一个人在oracle表中的地址数据[未显示到特定人和其他几个字段的映射]。

**StartDate                 Address             EndDate** <br/>

1。 10-JAN-2015 10:52:23 1 Grimshaw 12-JAN-2015 11:30:15
2. 12-JAN-2015 11:30:15 2 Ashwood 15-JAN-2015 03:17:05
第3。 15-JAN-2015 03:17:05 5 Green Drive 13-FEB-2015 06:03:55
4. 13-FEB-2015 06:03:55 6 Lightfoot关闭18-FEB-2015 17:37:01
5. 18-FEB-2015 17:37:01 7 Lightfoot Ln 15-MAR-2015 01:19:31

所有这些地址都有正确的日期顺序。这意味着,特定的人在2015年1月10日至2015年3月15日期间始终拥有有效地址]。 要求是,比如删除其中一个地址并相应地调整日期,以便不留任何空隙。我们有一个脚本删除特定的行但无法相应地更新其他行中的日期。 例如,如果我删除上面集合中的第3行,那么最终结果应该看起来像

**StartDate                 Address             EndDate** <br/>

1。 10-JAN-2015 10:52:23 1 Grimshaw 12-JAN-2015 11:30:15
2. 12-JAN-2015 11:30:15 2 Ashwood 13-FEB-2015 06:03:55
3. 13-FEB-2015 06:03:55 6 Lightfoot关闭18-FEB-2015 17:37:01
4. 18-FEB-2015 17:37:01 7 Lightfoot Ln 15-MAR-2015 01:19:31

使用已删除行的EndDate [即第3行]更新第2行的EndDate。

注意: 这里的记录编号1-5仅用于说明目的,表中没有任何此类列。

2 个答案:

答案 0 :(得分:0)

我通过假设以下条件

来编写此触发器
  1. 在表格中,将有person_id列代表每个人
  2. 当某行被删除时,对于End date行已删除行start date的行,将进行更新
  3. 删除行时,已删除行的EndDate列值将用于更新上一行的EndDate

    create or replace trigger product_update
    
    BEFORE DELETE on your_table_name
    for each row
    

    开始

    UPDATE your_table_name
       SET EndDate = :new.EndDate,
     WHERE EndDate = :new.StartDate
     AND PERSON_ID = :new.PERSON_ID;  
    

    端;

答案 1 :(得分:0)

我为您展示的设计模式创造了“行跨越依赖”一词。这是一列依赖于另一列但在另一列中的位置。问题是保持数据完整性是一场噩梦 - 正如你所看到的那样。

我建议完全删除EndDate列。如果这是你无权做的事情,那么你可以简单地忽略它。除了让你的生活变得悲惨之外,EndDate领域没有任何意义。

仅使用StartDate字段,地址从那时开始,一直持续到下一个更高的StartDate值。因此,如果删除指定的行,则1月12日开始的地址现在将持续到2月13日。您可以稍后插入一个新行,例如,1月20日的StartDate,它很适合序列:12月1日 - &GT; 1月20日 - &gt; 2月13日......

要实现的重要一点是每行独立于其他行。您可以插入,删除和更新您心脏的内容,只要日期值保持唯一,序列就不会被破坏。 StartDate是PK的一部分,只是强制执行唯一性。

自动,您不需要额外的努力,就可以保持完整的日期序列,没有间隙,也不会有任何永久性。这一点不能过分强调:没有办法“破坏”序列。即使两个日期仅相差毫秒(这可能意味着其中一个日期值错误),序列仍保持不变。如果其中一个日期错误,请将其更新为正确的值,而不必担心会破坏序列的完整性。

查看特定日期上哪个地址处于活动状态的查询实际上非常简单:

select  a.StartDate, a.Address
from    Addresses a
where   StartDate =(
        select  Max( StartDate )
        from    Addresses
        where   PersonID = a.PersonID
            and StartDate <= :AsOfDate );

如果您必须,可以重现StartDate / EndDate表单:

select  a.StartDate, a.Address, a1.StartDate as EndDate
from    Addresses a
left join Addesses a1
    on  a1.PersonID = a.PersonID
    and a1.StartDate =(
        select  Min( StartDate )
        from    Addresses
        where   PersonID = a.PersonID
            and StartDate > a.StartDate );

最后一个日期 - 代表“当前”地址的日期 - 将显示EndDate值NULL,这提供了标记当前行的额外好处。

实际上,您可以根据第二个查询创建一个视图,并为您的用户提供他们习惯看到的内容。另一个方便的视图将基于第一个查询,但使用sysdate而不是参数。这只会显示当前的地址。无论哪种方式,现在您不必为保持一行的StartDate值和不同行的EndDate值不断同步而烦恼。