2013-05-01 42 views
6

Tôi có ba bảng: Ứng dụngMS SQL Server bảng chéo chế

1) (AppID, Name)
2) Màn hình (ScreenId, Name)
3) Mối quan hệ (AppID, ScreenId)

Bây giờ tôi muốn áp dụng một số hạn chế trên bảng liên quan: Có thể gán cùng một màn hình cho nhiều ứng dụng, nhưng không thể có hai màn hình có cùng tên được gán cho cùng một ứng dụng.

Tôi biết tôi có thể thêm Screen.Name vào bảng quan hệ và sau đó tạo PK trên AppId và Screen.Name, nhưng tôi không muốn giải pháp như vậy, vì Screen.Name có thể thay đổi.

Tôi có các tùy chọn bổ sung nào để đạt được hạn chế như vậy?

Trả lời

8

Bạn có thể tạo một indexed view dựa trên các bảng RelationScreen và áp dụng một hạn chế duy nhất ở đó.

create view DRI_UniqueScreens 
with SCHEMABINDING 
as 
    select r.AppId,s.Name 
    from 
     [Schema].Relation r 
     inner join 
     [Schema].Screen s 
     on 
      r.ScreenId = s.ScreenId 
GO 
CREATE UNIQUE CLUSTERED INDEX IX_DRI_UniqueScreens 
    on DRI_UniqueScreens (AppId,Name) 
+0

Tôi tự hỏi liệu có cái gì đó như thế này không. :) Tốt hơn nhiều so với kích hoạt. :) – Jonathan

+0

Phương pháp này "xác thực" dữ liệu khi thay đổi tên màn hình hay nó sẽ chỉ kiểm tra dữ liệu khi truy cập chế độ xem? –

+2

@AlexDn - vâng, điều này sẽ thực thi ràng buộc khi thay đổi được thực hiện trong các bảng bên dưới. Nếu bạn truy cập trang tôi đã liên kết, bạn sẽ nhận thấy rằng có rất nhiều hạn chế về lượt xem được lập chỉ mục. Hầu hết các hạn chế này tồn tại * vì * chúng cho phép hoạt động bảo trì bắt buộc xảy ra trên mỗi giao dịch trong các bảng cơ sở một cách hiệu quả. –

0

Đây không phải là giải pháp tuyệt vời, nhưng bạn có thể thêm trình kích hoạt vào màn hình và bảng quan hệ chỉ kiểm tra những gì bạn đã sửa đổi đáp ứng tiêu chí của bạn và quay lại nếu không.

CREATE TRIGGER trgScreen ON Screen FOR INSERT, UPDATE 
AS 
BEGIN 
    IF EXISTS (SELECT r.AppID, s.Name FROM Screen s 
       INNER JOIN Relation r ON s.ScreenID = r.ScreenID 
       GROUP BY r.AppID, s.Name 
       HAVING count(*) > 1) 
     ROLLBACK TRANSACTION 
END 

CREATE TRIGGER trgRelation ON Relation FOR INSERT, UPDATE 
AS 
BEGIN 
    IF EXISTS (SELECT r.AppID, s.Name FROM Screen s 
       INNER JOIN Relation r ON s.ScreenID = r.ScreenID 
       GROUP BY r.AppID, s.Name 
       HAVING count(*) > 1) 
     ROLLBACK TRANSACTION 
END 
+0

Có, trình kích hoạt sẽ hoạt động, nhưng tôi đang cố gắng tránh trình kích hoạt càng nhiều càng tốt. –

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