我有一个人在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仅用于说明目的,表中没有任何此类列。
答案 0 :(得分:0)
我通过假设以下条件
来编写此触发器person_id
列代表每个人End date
行已删除行start date
的行,将进行更新删除行时,已删除行的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值不断同步而烦恼。