如何根据要删除的行调整其他行数据
Posted
技术标签:
【中文标题】如何根据要删除的行调整其他行数据【英文标题】:how to adjust other rows data based on a to be deleted row 【发布时间】:2015-05-18 17:06:29 【问题描述】:我在一个人的 oracle 表中有以下地址数据[未显示到特定人员和其他几个字段的映射]。
**StartDate Address EndDate** <br/>
1。 2015 年 1 月 10 日 10:52:23 1 格里姆肖 2015 年 1 月 12 日 11:30:15 2. 2015 年 1 月 12 日 11:30:15 2 阿什伍德 2015 年 1 月 15 日 03:17:05 3。 15-JAN-2015 03:17:05 5 绿色驱动器 13-FEB-2015 06:03:55 4. 2015 年 2 月 13 日 06:03:55 6 Lightfoot 关闭 2015 年 2 月 18 日 17:37:01 5. 2015 年 2 月 18 日 17:37:01 7 Lightfoot Ln 2015 年 3 月 15 日 01:19:31
所有这些地址都有正确的日期顺序。这意味着,一个特定的人总是在 2015 年 1 月 10 日到 2015 年 3 月 15 日之间拥有一个有效地址]。 要求是,说删除其中一个地址并相应地调整日期,以便不留空隙。我们有一个脚本可以删除特定行但无法相应地更新其他行中的日期。 例如,如果我删除上述集合中的第 3 行,则最终结果应如下所示
**StartDate Address EndDate** <br/>
1。 2015 年 1 月 10 日 10:52:23 1 格里姆肖 2015 年 1 月 12 日 11:30:15 2. 2015 年 1 月 12 日 11:30:15 2 阿什伍德 2015 年 2 月 13 日 06:03:55 3. 2015 年 2 月 13 日 06:03:55 6 Lightfoot 关闭 2015 年 2 月 18 日 17:37:01 4. 2015 年 2 月 18 日 17:37:01 7 Lightfoot Ln 2015 年 3 月 15 日 01:19:31
第 2 行的 EndDate 更新为已删除行的 EndDate [即第 3 行]。
注意: 此处的记录编号 1-5 仅用于说明目的,表格中没有任何此类列。
【问题讨论】:
你使用 sql server 还是 oracle? Oracle...主要是寻找一些创新的 SQL 或 pl/sql 方式,否则... 它是否总是更新以已删除行的开始日期结束的行..在您的示例中,已删除行的开始日期为 15,您更新结束日期为 15 的行..您更新结束日期与删除行的结束日期..总是一样吗? 你试过我的答案了吗? 【参考方案1】:我通过假设以下条件编写了这个触发器
-
在表格中会有一个
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;
结束;
【讨论】:
【参考方案2】:我为您展示的设计模式创造了“行跨越依赖”一词。那是一列依赖于另一列但在不同行中的地方。问题在于,维护数据完整性是一场噩梦——正如您所见。
我建议完全删除 EndDate 列。如果那是您无权做的事情,那么您可以简单地忽略它。 EndDate 字段没有任何用途,只会让您的生活变得悲惨。
仅使用 StartDate 字段,地址从那个时间开始并持续到下一个更高的 StartDate 值。因此,如果您删除指定的行,则从 1 月 12 日开始的地址现在将持续到 2 月 13 日。您稍后可以插入一个新行,其 StartDate 为 1 月 20 日,它非常适合序列:1 月 12 日-> 1 月 20 日 -> 2 月 13 日...
要意识到的重要一点是每一行都独立于其他行。您可以随心所欲地插入、删除和更新,只要日期值保持唯一,序列就不会中断。唯一性仅由作为 PK 一部分的 StartDate 强制执行。
自动地,无需您付出额外的努力,就可以保持完整的日期序列,没有间隙,也不会重复。这一点怎么强调都不为过:不可能“打破”这个顺序。即使两个日期仅相差几毫秒(这可能意味着其中一个日期值错误),序列仍然保持不变。如果其中一个日期错误,请将其更新为正确的值,而不必担心会破坏序列的完整性。
查询哪个地址在特定日期处于活动状态实际上非常简单:
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 值不断同步而烦恼。
【讨论】:
以上是关于如何根据要删除的行调整其他行数据的主要内容,如果未能解决你的问题,请参考以下文章