2016-04-05 17 views
5

Tôi có một bảng số điện thoại được sở hữu bởi một công ty và một bảng các bản ghi cuộc gọi điện thoại. Mỗi bản ghi cuộc gọi bao gồm (không null) nguồn và số đích. Tôi được cung cấp ràng buộc toàn vẹn rằng số nguồn hoặc số đích, nhưng không được cả hai, được phép là số không nằm trong bảng số điện thoại (vì chúng là số không thuộc sở hữu của công ty này). Nói cách khác, tôi cần đảm bảo rằng ít nhất một trong số họ là một khóa ngoại vào bảng số điện thoại.Ràng buộc SQL: hai thuộc tính, ít nhất một đối sánh khóa ngoài trên cùng một bảng

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

Những âm thanh sau đây giống như những gì tôi muốn, nhưng không phải là SQL hợp lệ:

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

Có cách nào để xác định này trong DDL? Nếu không, làm thế nào tôi sẽ viết một kích hoạt để thực thi điều này?

Trả lời

3

được sửa đổi: Dưới đây là một ý tưởng sử dụng DDL và không sử dụng kích hoạt:

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

Tạo một chức năng để xác nhận chính nước ngoài "bằng tay".

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; 

Nếu bạn đang ở trên 11g trở lên, sau đó thêm cột ảo và thêm kiểm tra trên cột đó

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

Hãy kiểm tra

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

Không thể lấy lại để kiểm tra đến bây giờ , nhưng cái này hoạt động. Cảm ơn! Tôi đang ở trong một khóa học SQL nhưng các cột ảo chưa được thảo luận. Đây có phải là cách thông thường hay cách "lý tưởng", thực thi ràng buộc như thế này? Tôi đã không có một sở thích mạnh mẽ cho DDL trên gây nên nhưng tôi đã stumped một trong hai cách. –

+0

Theo tôi, không cần phải có một ràng buộc như thế này, điều này có thể báo hiệu vấn đề thiết kế mô hình dữ liệu. Đối với bất cứ điều gì khác trên ưu tiên kích hoạt tôi có thể đề nghị đọc "gây nên là ác" google hits. Đối với các cột ảo, thực tế bạn có thể làm nhiều hơn với chúng, hãy kiểm tra cột của Oracle Magazine 2008-March Tom Kyte để tham khảo: http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28asktom -087592.html –

Các vấn đề liên quan