0

I've got a table in an Oracle 11gR2 database that contains five sequential fields, like Field1, Field2, Field3, Field4, and Field5.

These fields are related:

  • If Field2 is populated, Field1 has to be populated.
  • If Field5 is populated, all Fieldn fields should be populated.

What is the best way to validate that these fields are populated correctly?

For instance, the query should return cases where Field3 is populated, but Field1 and Field2 are not. Or when just Field4 is populated. Or when Field1 and Field3 are populated. Etc. I'd like to avoid 25 different conditions in my filter if possible.

Any help would be appreciated.

4

2 に答える 2

1

唯一の有効なシナリオが、ギャップなしでフィールドを順番に埋めることである場合、これはあなたが言っていることだと思いますが、入力された「最も高い」フィールドと入力されたフィールドの数を計算できます。それらを比較します。ギャップがある場合、これらの 2 つの数値は異なります。例えば:

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が指摘しているように、(別の SQL Fiddle に示されている) の代わりに使用できます。これnvl2非標準ですが、間違いなくより明確です。case

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 に答える