2013-08-31 67 views
0

我在Oracle 11gR2數據庫中有一個表,其中包含五個順序字段,如Field1Field2Field3,Field4Field5Oracle序列字段驗證

這些字段相關:

  • 如果Field2填充,Field1必須被填充。
  • 如果填充Field5所有字段N字段應該填充。

驗證這些字段是否正確填充的最佳方法是什麼?

例如,查詢應該返回其中填充字段3例,但字段1和Field2都沒有。或者當只有Field4被填充時。或者當Field1和Field3被填充。等如果可能的話,我想在我的過濾器中避免25種不同的條件。

任何幫助,將不勝感激。

回答

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

如果唯一有效的方案是滿山遍野有序,沒有間隙,我認爲這是你說的話,那麼你可以計算出填充的「最高」字段以及填充的字段數量,並對它們進行比較。如果我們有差距,那麼這兩個數字將會不同。例如:

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); 

...但除了檢查本身也許更清澈,我不認爲它增加了很多。

+0

使用'nvl2'而不是'case',它使代碼更具可讀性。 –

+0

@ Michael-O - 我通常更喜歡'case',但我已經添加了'nvl2'版本作爲完美的替代選擇。謝謝。 –

+0

+1。限制。 –