2016-04-05 11 views
5

Şirkete ait bir telefon numarasına ve telefon çağrıları tablosuna sahibim. Her çağrı kaydı (boş olmayan) kaynak ve hedef numaraları içerir. Kaynak numarasının veya hedef numarasının, ancak her ikisinin de değil, telefon numarası tablosunda bulunmayan numaralar olmasına izin verdiğim (bu şirkete ait olmayan numaralar oldukları) bütünlük kısıtlaması verildi. Diğer bir deyişle, en az birinin telefon numarası tablosuna yabancı bir anahtar olduğundan emin olmalıyım.SQL kısıtlaması: iki öznitelik, aynı tabloda en az bir yabancı anahtar eşleşmesi

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

istediğim ama geçerli bir SQL ne olmadığını gibi aşağıdaki sesler:

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

DDL bu belirtmek için bir yolu var mı? Değilse, bunu uygulamak için nasıl bir tetikleyici yazarım? Düzenlenen

cevap

3

:

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

"elle" yabancı anahtarı doğrulamak için bir işlev oluşturun: İşte DDL kullanılarak ve tetiği kullanmayan başka bir fikirdir.

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; 

sen 11g iseniz ve yukarı, sonra da sanal bir sütun eklemek ve o sütun

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

edelim testi üzerindeki kontrolünü eklemek

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

şimdi til geri testine alınamadı ama bu işe yarıyor. Teşekkürler! SQL kursundayım ama sanal sütunlar tartışılmamıştı. Bu, ortak bir yol mu, yoksa böyle bir kısıtlamanın uygulanmasının "ideal" bir yolu mu? Tetikleyicilerden DDL için güçlü bir tercihim yoktu ama her iki şekilde de güldüm. –

+0

Aklımda bunun gibi bir kısıtlamaya ihtiyaç duyulmaması çok yaygın değil, bu durum veri modeli tasarımı konusuna işaret edebilir. Tetikleyicilerin tercihi dışındaki her şey için "tetikleyiciler kötülük" kelimesini okumanızı önerebilirim. Sanal sütunlar için aslında onlarla yapabileceğiniz daha çok şey var, Oracle Magazine 2008-Mart Tom Kyte'nin referans için sütununu kontrol edin: http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28asktom -087592.html –

İlgili konular