2016-11-22 10 views
3

Iは、5つの列を含むテーブルを有する:A、B、C、DおよびEテーブル内でこの動作を保証するデータベース制約を与える方法はありますか?

そして、私は、次の制限を遵守する必要があります

  • Aが主キーです。
  • Bの場合、1つのCしか存在できません。 2-1; 3-2ではなく1-2である。
  • B-CおよびDは任意の値をとることができますが、繰り返すことはできません。 1-1 2;再び1-1 1ではありません。
  • Eは任意の値をとります。だから、

、次の順序

| A | B | C | D | E | 

| 1 | 1 | 1 | 1 | 1 | -> OK 

| 2 | 1 | 2 | 1 | 1 | -> Should fail, because there is a B with another C, 1-2 must be 1-1. 

| 3 | 1 | 1 | 2 | 1 | -> OK 

| 4 | 1 | 1 | 2 | 1 | -> Should fail, because relation between B-C and D is repeated. 

| 5 | 2 | 1 | 1 | 1 | -> OK 

を考慮すると、データベース内のいくつかの制約によって、この動作に準拠する方法はありますか?

ありがとうございます!私はB - C - Dルールのトリガ

を作成しますB - Cルールについては

+0

は、あなたの代わりにトリガーを検討したことがありますか? –

+0

構造が正規化されていないように聞こえます。 – DCookie

+0

@JuanCarlosOropezaはい、この場合は使用しないことをお勧めします。 – NachoB

答えて

1

AとEは、質問とは無関係であり、無視することができます。

BCDルールは、BCDに一意のインデックスを作成することで簡単に解決できます。

すべてのBについて1つのCしかない場合、DBは正規化されません。BとCを使用して新しいテーブルを作成します。Bを主キーにするか、Bに一意のインデックスを作成します。元のテーブルからCを削除します。 (BCDのユニークなインデックスがBD上でユニークなインデックスになります)

テーブルを正規化せずに、私は制約でそれを行う方法はないと思います。あなたは確かに引き金やコードでそれを行うことができます。

+0

私はすべての人の中で最も正確な答えを私に与えたと思います。 当面は、コードを使用して問題を解決しようとします。 おかげさまで、皆様のご協力をいただきました! – NachoB

1

あなたはユニーク制約に

ALTER TABLE t ADD CONSTRAINT uni_BCD UNIQUE (B,C,D); 
0

をしたいようにこの条件がBの場合

些細なことではないに見えますただ1つのC、すなわち:1-1であることができる。 2-1; 3-2ではなく1-2である。 OracleはCREATE ASSERTIONがサポートされていないので、

、(すぐに、私たちは願っています!)

したがって、あなたは、INSERT/UPDATE AFTERこの制約、またはelseステートメント・レベルを強化するために、第2のテーブルが関与する必要があります引き金。

私が行うことは、2番目のテーブルを作成し、ビュー上でINSTEAD OFトリガーを介して維持し、すべてのアプリケーションDMLがビューを介して行われていることを確認することです。 (また、単にテーブルの上に定期的にトリガーを作成することができ、それは第二のテーブルを維持。それはちょうど私の好みではありません。私はINSTEAD OFをより柔軟でより見えるようにトリガーを見つける持っています。)

を、それははっきりしていない場合2番目のテーブルの目的は、制約をFOREIGN KEYという制約として適用できることです。 2番目のテーブルのUNIQUEまたはPRIMARY KEYの制約により、Bの各値が1回だけ表示されます。

ここ

は、そのアプローチのためのサンプルコードです:

--DROP TABLE table1_parent; 
--DROP TABLE table1; 


CREATE TABLE table1_parent 
(b number NOT NULL, 
    c number NOT NULL, 
    constraint table1_parent_pk PRIMARY KEY (b), 
    constraint table1_parent_u1 UNIQUE (b, c)); 

CREATE TABLE table1 
(
    a NUMBER NOT NULL, 
    b NUMBER NOT NULL, 
    c NUMBER NOT NULL, 
    d NUMBER NOT NULL, 
    e NUMBER NOT NULL, 
    CONSTRAINT table1_pk PRIMARY KEY (a), -- "A is the primary key." 
    CONSTRAINT table1_fk FOREIGN KEY (b, c) REFERENCES table1_parent (b, c), -- "For a B there can only be one C, ie: 1-1 ; 2-1 ; 3-2 but not 1-2." 
    CONSTRAINT table1_u2 UNIQUE (b, c, d) -- "B-C and D can take any value bue can not be repeated, ie: 1-1 1 ; 1-1 2 ; not 1-1 1 again." 
); 

CREATE INDEX table1_n1 ON table1 (b,c); -- Always index foreign keys 

CREATE OR REPLACE VIEW table1_dml_v AS SELECT * FROM table1; 

CREATE OR REPLACE TRIGGER table1_dml_v_trg INSTEAD OF INSERT OR UPDATE OR DELETE ON table1_dml_v 
DECLARE 
    l_cnt NUMBER; 
BEGIN 
    IF INSERTING THEN 
    BEGIN 
     INSERT INTO table1_parent (b, c) VALUES (:new.b, :new.c); 
    EXCEPTION 
     WHEN dup_val_on_index THEN 
     NULL; -- parent already exists, no problem 
    END; 

    INSERT INTO table1 (a, b, c, d, e) VALUES (:new.a, :new.b, :new.c, :new.d, :new.e); 
    END IF; 

    IF DELETING THEN 
    DELETE FROM table1 WHERE a = :old.a; 

    SELECT COUNT(*) INTO l_cnt FROM table1 WHERE b = :old.b AND c = :old.c; 

    IF l_cnt = 0 THEN 
     DELETE FROM table1_parent WHERE b = :old.b AND c = :old.c; 
    END IF; 
    END IF; 

    IF UPDATING THEN 
    BEGIN 
     INSERT INTO table1_parent (b, c) VALUES (:new.b, :new.c); 
    EXCEPTION 
     WHEN dup_val_on_index THEN 
     NULL; -- parent already exists, no problem 
    END; 

    UPDATE table1 SET a = :new.a, b = :new.b, c = :new.c, d = :new.d, e = :new.d WHERE a = :old.a; 

    SELECT COUNT(*) INTO l_cnt FROM table1 WHERE b = :old.b AND c = :old.c; 

    IF l_cnt = 0 THEN 
     DELETE FROM table1_parent WHERE b = :old.b AND c = :old.c; 
    END IF; 

    END IF;  
END; 


insert into table1_dml_v (a,b,c,d,e) VALUES (1,1,1,1,1); 
insert into table1_dml_v (a,b,c,d,e) VALUES (2,1,2,1,1); 
insert into table1_dml_v (a,b,c,d,e) VALUES (3,1,1,2,1); 
insert into table1_dml_v (a,b,c,d,e) VALUES (4,1,1,2,1); 
insert into table1_dml_v (a,b,c,d,e) VALUES (5,2,1,1,1); 
0

システムで高速リフレッシュされたマテリアライズド・ビューがサポートされている場合は、次の方法を試してください。
私は現在この機能にアクセスしていないので、解決策を確認することはできません。

create materialized view log on t with primary key; 

create materialized view t_mv 
refresh fast 
as 
select  b,c 
from  t 
group by b,c 
; 

alter table t_mv add constraint t_mv_uq_b unique (b); 

やコースオフ:

alter table t add constraint t_uq_a_b_c unique (b,c,d); 
関連する問題