2016-04-05 6 views
5

私は会社が所有する電話番号のテーブルと電話通話のテーブルを持っています。すべてのコールレコードには、(nullではない)発信元番号と宛先番号が含まれます。ソース番号または宛先番号のどちらかではなく、両方が電話番号テーブルにない番号であることが許可されているという整合性制約が与えられています(この番号はこの会社の所有ではないためです)。つまり、少なくとも1つが電話番号テーブルの外部キーであることを確認する必要があります。SQL制約:2つの属性、同じテーブルで少なくとも1つの外部キーが一致します

create table phonenumber (
    phonenum numeric(10,0) not null, 
    primary key (phonenum) 
); 
create table call_record (
    URID varchar(20) not null, 
    c_src numeric(10,0) not null, 
    c_dst numeric(10,0) not null, 
    primary key (URID) 
); 

私はしたいが、有効なSQLがないものなどは、以下の音:

constraint call_constraint check (
    foreign key (c_src) references phonenumber (phonenum) or 
    foreign key (c_dst) references phonenumber (phonenum) 
) 

がDDLでこれを指定する方法はありますか?もしそうでなければ、私はこれを強制するトリガーをどのように書いていますか?編集

答えて

3

create table phonenumber (
    phonenum numeric(10,0) not null, 
    primary key (phonenum) 
); 

は「手で」外部キーを検証する機能を作成します。 ここでDDLを使用して、トリガーを使用していないもう一つの考えです。

CREATE OR REPLACE FUNCTION call_check(p_src NUMBER, p_dst NUMBER) RETURN VARCHAR2 DETERMINISTIC IS 
BEGIN 
    FOR x IN (SELECT COUNT(*) c 
       FROM (SELECT 1 
         FROM phonenumber 
        WHERE phonenum = p_src 
        UNION ALL 
        SELECT 1 
         FROM phonenumber 
        WHERE phonenum = p_dst)) LOOP 
    IF x.c>=1 AND x.c <= 2 THEN 
     RETURN 'OK'; 
    END IF; 
    END LOOP; 
    RETURN 'NOK'; 
END; 

あなたは11グラムにしている場合は、最大、仮想列を追加し、その列

--drop table call_record 
create table call_record (
    URID varchar(20) not null, 
    c_src numeric(10,0) not null, 
    c_dst numeric(10,0) not null, 
    call_check_col GENERATED ALWAYS AS (call_check(c_src, c_dst)), 
    primary key (URID) 
); 

ALTER TABLE call_record ADD CONSTRAINT call_check_con CHECK (call_check_col='OK'); 

レッツ・テストのチェックを追加

SQL>  INSERT INTO phonenumber VALUES ('123'); 
1 row inserted 
SQL>  INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C1', '123', '321'); 
1 row inserted 
SQL>  INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C3', '123', '123'); 
1 row inserted 
SQL>  INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C2', '321', '321'); 
INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C2', '321', '321') 
ORA-02290: check constraint (TST.CALL_CHECK_CON) violated 
+0

今ゴマバックテストに取得できませんでした。しかし、これは動作します。ありがとう!私はSQLコースに入っていますが、仮想列は議論されていませんでした。これは、このような制約を強制する一般的な方法か、「理想的な」方法ですか?私はDDLオーバートリガーを強く好みませんでしたが、いずれにしても困惑しました。 –

+0

このような制約が必要なことはあまり一般的ではなく、データモデルの設計上の問題を示すかもしれません。他の何かのために私が "トリガは悪い" Googleヒットを読むことを示唆することができますプリファレンスをトリガします。仮想列に関しては、実際にはもっと多くのことができます.Oracle Magazine 2008-March Tom Kyteのコラムを参照してください。http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28asktom -087592.html –

関連する問題