7

テーブルに A、B、C の 3 つの列があるとします。列 A に値 (たとえば x) を挿入する場合、B または C のいずれかが x に等しいタプルを挿入できないようにしたいと考えています。 、つまり、値 x は、すべてのタプルについて列 A に対して一意のままにする必要があります。

x は、他のタプルの A で繰り返すことができることに注意してください。

SQL の UNIQUE 句は知っていますが、これは値が特定の列に 1 回だけ出現するようにするためのものです。Oracle の CHECK ステートメントではサブクエリが許可されていないため、これを実装する方法がわかりません。

編集(さらに情報を追加するため)

主キーは Employee_Number で、問題の 3 つの列は LandlineNo、MobileNo、VOIP です。したがって、これが 1 つのエントリであるとします。

Employee_Number = 1, LandlineNo = x, MobileNo = y, VOIP = z

次に、別のタプルのこのエントリは許可されません -

Employee_Number = 2, LandlineNo = a, MobileNo = x, VOIP = c

一方、これは問題ありません(はい、2人の従業員が同じタイプの同じ番号を持つことができます)

Employee_Number = 2, LandlineNo = x, MobileNo = b, VOIP = c
4

2 に答える 2

2
CREATE MATERIALIZED VIEW mv_my
BUILD IMMEDIATE
REFRESH FAST ON COMMIT AS
SELECT DISTINCT
    CASE 
        WHEN t2.Employee_Number IS NOT NULL THEN 1
        WHEN t3.Employee_Number IS NOT NULL THEN 1
        WHEN t4.Employee_Number IS NOT NULL THEN 1
        ELSE 0
    END AS wrong
FROM table t1
    LEFT JOIN table t2 ON t2.MobileNo = t1.LandlineNo AND t2.Employee_Number != t1.Employee_Number
    LEFT JOIN table t3 ON t3.VOIP = t1.LandlineNo AND t3.Employee_Number != t1.Employee_Number
    LEFT JOIN table t4 ON t4.VOIP = t1.MobileNo AND t4.Employee_Number != t1.Employee_Number
/

ALTER TABLE mv_my ADD CHECK(wrong = 0)
/

オラクルのバージョン ( doc )によっては、機能する場合と機能しない場合があります。

于 2013-11-02T18:41:53.317 に答える
1
create table table1(
   a varchar2(20) not null,
   b varchar2(20) not null,
   c varchar2(20) not null
)
/
create table ctrs (
   val varchar2(20) unique,
   ctr_a int,
   ctr_b int,
   ctr_c int,
   check(ctr_a*ctr_b+ctr_a*ctr_c+ctr_b*ctr_c=0)
)
/
create trigger table1_trg 
before insert or update or delete on table1
for each row
begin
   if deleting then 
      update ctrs set ctr_a = ctr_a - 1 where val = :old.a;
      update ctrs set ctr_b = ctr_b - 1 where val = :old.b;
      update ctrs set ctr_c = ctr_c - 1 where val = :old.c;
   elsif inserting then
      merge into ctrs using (
        select :new.a as x from dual union all
        select :new.b as x from dual union all
        select :new.c as x from dual
      )
      on (val = x)
      when not matched then 
         insert (val, ctr_a, ctr_b, ctr_c) values (x, 0, 0, 0);
      update ctrs set ctr_a = ctr_a + 1 where val = :new.a;
      update ctrs set ctr_b = ctr_b + 1 where val = :new.b;
      update ctrs set ctr_c = ctr_c + 1 where val = :new.c;
   else
      update ctrs set ctr_a = ctr_a - 1 where val = :old.a;
      update ctrs set ctr_b = ctr_b - 1 where val = :old.b;
      update ctrs set ctr_c = ctr_c - 1 where val = :old.c;
      merge into ctrs using (
        select :new.a as x from dual union all
        select :new.b as x from dual union all
        select :new.c as x from dual
      )
      on (val = x)
      when not matched then 
         insert (val, ctr_a, ctr_b, ctr_c) values (x, 0, 0, 0);
      update ctrs set ctr_a = ctr_a + 1 where val = :new.a;
      update ctrs set ctr_b = ctr_b + 1 where val = :new.b;
      update ctrs set ctr_c = ctr_c + 1 where val = :new.c;
   end if;
end;
/

フィドル

于 2013-11-02T17:53:40.193 に答える