0

我尝试在这里查看与我尝试创建的内容密切相关的主题,但到目前为止我还没有运气。我正在尝试基于 current_flag、id 和 current_year 的组合创建一个约束/索引。id 不是表的主键。current_flag='Y'的current_flag、id和current_year的组合只能有1条记录,current_flag='N'的current_flag、id和current_year的组合可以有n条记录。

current_flag='Y' ID=1 current_year=2013

current_flag='N' ID=1 current_year=2013

current_flag='N' ID=1 current_year=2013

current_flag='Y' ID=2 current_year=2013

current_flag='Y' ID=3 current_year=2013

逻辑是如果在该 ID 下插入一条新记录,current_year,并且 current_flag='Y'(假设插入的是新的当前记录) 之前的当前记录将根据 ID 设置为 current_flag='N'和 current_year

4

2 回答 2

1

您可以创建一个索引来强制每个 id 和当前年份的唯一组合只有一行可以具有 current_flag 的值“Y”:

create unique index my_index
on     my_table (
         case current_flag when 'Y' then ID           end,
         case current_flag when 'Y' then current_year end);

从公式中可以看出,如果 current_flag 不是“Y”,则索引中的条目为空,因此不包含在索引中以进行唯一性检查。

但是,这有点小题大做。

恕我直言,更好的解决方案是,在 ID 和 current_year 的值上唯一的父表包含一个列,用于标识该表的主键,该行被视为该 id 和 current_year 的默认值。

于 2013-06-17T21:33:02.460 回答
0

您可以毫无问题地在这三列上创建索引:

create index i_my_table on my_table(id, current_flag, current_year);

但是,您无法将这种行为限制在单个表中。

但是,您有几种可能性。如果您想确保没有人可以通过插入数据来破坏您的条件,那么您可以执行以下操作:

  1. 将当前表拆分为两个,一个 where current_flag = 'Y'( TABLEY) 和另一个 where current_flag = 'N'( TABLEN)。

  2. 在 上创建主键TABLEY。这可确保您保持自己的独特性。

  3. 创建一个 BEFORE UPDATE 触发器TABLEY,将更新的记录插入TABLEN.

  4. 创建一个约束以TABLEN确保标志只能是 N。或者,您可以完全删除此列,因为它的值从表中已知。这取决于您对具有数据库后端访问权限的人员的信任程度。

  5. 当您需要在此标志所在的位置插入新数据时,请Y使用 MERGE:

    merge into tabley o
    using ( ... ) n
       on ( o.id = n.id
            and o.current_year = n.current_year )
     when matched then
          update ...
     when not matched then
          insert ...
    

    由于触发器,每当您用新记录覆盖以前为 Y 的记录时,该记录将被放入TABLEN. 您的新记录将保留。

  6. 对于奖励积分,创建一个物化视图,它是TABLEY和的 UNION TABLEN

于 2013-06-17T21:23:39.770 回答