2013-11-02 26 views
7

Giả sử tôi có 3 cột trong bảng - A, B và C. Tôi muốn đảm bảo rằng nếu tôi chèn một số giá trị (giả sử x) vào cột A, tôi không thể chèn một tuple có B hoặc C bằng x, tức là, giá trị x sẽ duy trì duy nhất cho cột A cho tất cả các bộ dữ liệu.Giá trị ràng buộc SQL Oracle duy nhất trong nhiều cột

Lưu ý rằng x có thể được lặp lại trong A đối với một số bộ dữ liệu khác.

Tôi biết về mệnh đề UNIQUE trong SQL, nhưng đó chỉ là để đảm bảo rằng giá trị xuất hiện trong một cột cụ thể chỉ một lần. Vì các câu lệnh CHECK trong Oracle không cho phép các truy vấn con, tôi không thể tìm ra cách thực hiện điều này.

EDIT (thêm biết thêm)

Tiểu học trọng điểm là Employee_Number, trong khi 3 cột trong câu hỏi là LandlineNo, MobileNo và VOIP. Do đó cho rằng đây là một bài dự thi:

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

Sau đó, cụm từ này cho tuple khác sẽ KHÔNG được phép -

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

Mặt khác, chương trình này sẽ là tốt (có, 2 nhân viên có thể có cùng một số cùng loại)

Employee_Number = 2, LandlineNo = x, MobileNo = b, VOIP = c 
+0

Bạn có thể mở rộng câu hỏi của bạn với một ví dụ về hàng tốt và xấu? Cấu trúc và khóa chính của bảng là gì? –

+3

Bạn có bị mắc kẹt với thiết kế bảng này không? Những gì bạn đang yêu cầu ist để có mỗi số đảm bảo được một loại nhất định. Vì vậy, tại sao không có một bảng "con số", primay chính là số (hoặc một id cộng với một ràng buộc duy nhất trên các con số nếu bạn thích điều đó) và sau đó bạn có một loại cột. Vì vậy, mỗi số là duy nhất và có một loại. Sau đó, trong bảng nhân viên của bạn, bạn chỉ có ba khóa ngoài cho bảng số đó (tức là ba số hoặc ba id). –

+0

bạn đang sử dụng phiên bản Oracle nào? – Sebas

Trả lời

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

Nó có thể hoặc không thể làm việc tùy thuộc vào phiên bản oracle của bạn (doc)

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

fiddle

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