Oracle顺序字段验证

时间:2013-08-31 01:26:18

标签: sql oracle oracle11gr2

我在Oracle 11gR2数据库中有一个表,其中包含五个连续字段,例如Field1Field2Field3Field4Field5

这些字段是相关的:

  • 如果填充了Field2,则必须填充Field1
  • 如果填充了Field5,则应填充所有 Fieldn字段。

验证这些字段是否填充正确的最佳方法是什么?

例如,查询应返回填充Field3的情况,但不返回Field1和Field2。或者只填充Field4。或者填充Field1和Field3时。等等。如果可能的话,我想避免在我的过滤器中使用25种不同的条件。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:3)

可能最简单的方法是蛮力方法:

select t.*
from t
where (t.field1 is null and coalesce(t.field2, t.field3, t.field4, t.field5) is not null) or
      (t.field2 is null and coalesce(t.field3, t.field4, t.field5) is not null) or
      (t.field3 is null and coalesce(t.field4, t.field5) is not null) or
      (t.field4 is null and t.field5 is not null);

答案 1 :(得分:1)

如果唯一有效的方案是按顺序填充字段,没有间隙,我认为这就是你所说的,那么你可以计算出填充的“最高”字段和字段数填充,并比较它们。如果我们有差距,那么这两个数字将是不同的。 e.g:

select field1, field2, field3, field4, field5 from (
  select field1, field2, field3, field4, field5,
    case when field1 is not null then 1 else 0 end
      + case when field2 is not null then 1 else 0 end
      + case when field3 is not null then 1 else 0 end
      + case when field4 is not null then 1 else 0 end
      + case when field5 is not null then 1 else 0 end as cnt,
    greatest(case when field1 is not null then 1 else 0 end,
      case when field2 is not null then 2 else 0 end,
      case when field3 is not null then 3 else 0 end,
      case when field4 is not null then 4 else 0 end,
      case when field5 is not null then 5 else 0 end) as grt
  from my_table
)
where cnt != grt;

SQL Fiddle demo

正如Michael-O指出的那样,您可以使用nvl2代替case(显示在another SQL Fiddle中),这是非标准的,但可以说更清晰:

select field1, field2, field3, field4, field5 from (
  select field1, field2, field3, field4, field5,
    nvl2(field1, 1, 0) + nvl2(field2, 1, 0) + nvl2(field3, 1, 0)
      + nvl2(field4, 1, 0) + nvl2(field5, 1, 0) as cnt,
    greatest(nvl2(field1, 1, 0), nvl2(field2, 2, 0), nvl2(field3, 3, 0),
      nvl2(field4, 4, 0), nvl2(field5, 5, 0)) as grt
  from t42
)
where cnt != grt;

如果你想强制执行此操作,你可以添加一个检查约束来进行相同的比较:

alter table my_table add constraint my_check check (
  case when field1 is not null then 1 else 0 end
    + case when field2 is not null then 1 else 0 end
    + case when field3 is not null then 1 else 0 end
    + case when field4 is not null then 1 else 0 end
    + case when field5 is not null then 1 else 0 end
  = greatest(case when field1 is not null then 1 else 0 end,
      case when field2 is not null then 2 else 0 end,
      case when field3 is not null then 3 else 0 end,
      case when field4 is not null then 4 else 0 end,
      case when field5 is not null then 5 else 0 end));

由于您使用的是11gR2,因此您也可以使用虚拟列:

alter table my_table add cnt generated always as
  (case when field1 is not null then 1 else 0 end
    + case when field2 is not null then 1 else 0 end
    + case when field3 is not null then 1 else 0 end
    + case when field4 is not null then 1 else 0 end
    + case when field5 is not null then 1 else 0 end);

alter table my_table add grt generated always as
  (greatest(case when field1 is not null then 1 else 0 end,
    case when field2 is not null then 2 else 0 end,
    case when field3 is not null then 3 else 0 end,
    case when field4 is not null then 4 else 0 end,
    case when field5 is not null then 5 else 0 end));

alter table my_table add constraint my_check check (cnt = grt);

...但除了检查本身可能更清楚之外,我认为它不会增加太多。