0

我在 Oracle11gR2数据库中有一个表,其中包含五个顺序字段,例如Field1Field2Field3Field4Field5

这些字段是相关的:

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

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

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

任何帮助,将不胜感激。

4

2 回答 2

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);
于 2013-08-31T02:20:54.927 回答
1

如果唯一有效的情况是按顺序填写字段,没有空白,我认为这就是您所说的,那么您可以计算出填充的“最高”字段和填充的字段数,并且比较它们。如果我们之间存在差距,那么这两个数字将会不同。例如:

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 小提琴演示

正如Michael-O指出的那样,您可以使用nvl2而不是case(在另一个 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);

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

于 2013-09-01T10:14:00.297 回答