2009-06-10 35 views
22

Tôi tự hỏi thiết kế nào tốt hơn cho bảng giao lộ cho mối quan hệ nhiều-nhiều.Thiết kế Quan hệ Nhiều đến Nhiều - Thiết kế Bảng Giao nhau

Hai cách tiếp cận tôi đang xem xét là:

CREATE TABLE SomeIntersection 
(
    IntersectionId UNIQUEIDENTIFIER PRIMARY KEY, 
    TableAId UNIQUEIDENTIFIER REFERENCES TableA NOT NULL, 
    TableBId UNIQUEIDENTIFIER REFERENCES TableB NOT NULL, 
    CONSTRAINT IX_Intersection UNIQUE(TableAId, TableBId) 
) 

hoặc

CREATE TABLE SomeIntersection 
(
    TableAId UNIQUEIDENTIFIER REFERENCES TableA NOT NULL, 
    TableBId UNIQUEIDENTIFIER REFERENCES TableB NOT NULL, 
    PRIMARY KEY(TableAId, TableBId) 
) 

Có lợi ích cho một trong khác không?
CHỈNH SỬA 2: **** Xin lưu ý: Tôi định sử dụng Entity Framework để cung cấp API cho cơ sở dữ liệu. Với ý nghĩ đó, liệu một giải pháp có hoạt động tốt hơn với EF so với cái kia không?

EDIT: Trên ghi chú liên quan, đối với bảng giao nhau mà hai cột tham chiếu cùng một bảng (ví dụ bên dưới), có cách nào để làm cho hai trường khác nhau trên bản ghi không?

CREATE TABLE SomeIntersection 
(
    ParentRecord INT REFERENCES TableA NOT NULL, 
    ChildRecord INT REFERENCES TableA NOT NULL, 
    PRIMARY KEY(TableAId, TableBId) 
) 

tôi muốn ngăn chặn những điều sau

ParentRecord   ChildRecord 
================================= 
     1     1   --Cyclical reference! 
+3

Để ngăn chặn ví dụ của bạn (được gọi là "tự tham khảo"), nó là đủ để thêm một hạn chế kiểm tra về mức độ TABLE " ALTER TABLE dbo.SomeIntersection ADD CONSTRAINT CHK_SomeIntersection_SelfRefNoNoNo CHECK (ParentRecord <> ChildRecord) " --- Nhưng bạn sẽ không giải quyết được trường hợp A-> B-> C-> A theo cách đơn giản này. – van

+0

Tôi lo lắng về việc tự tham khảo nhiều hơn so với tham khảo, cảm ơn! –

Trả lời

9

Phiên bản thứ hai là tốt nhất đối với tôi, nó tránh việc tạo chỉ mục bổ sung.

+0

Tôi đã chấp nhận câu trả lời này vì nó hoạt động tốt nhất với Entity Framework. Bảng giao nhau/giao lộ gấp nếp độc đáo vào các thực thể được tạo trong mô hình. –

+1

Bạn sẽ cần một chỉ mục khác trong phiên bản thứ hai nếu bạn muốn truy cập vào bảng giao lộ từ Bảng B. –

12

Đó là một chủ đề của một số cuộc tranh luận. Tôi thích hình thức đầu tiên bởi vì tôi xem xét nó tốt hơn để có thể tra cứu hàng ánh xạ bằng một giá trị duy nhất, và thích thực thi một sự nhất quán ngu ngốc có lẽ có một khóa chính cột đơn có sẵn trong mỗi bảng mà không bị lỗi. Những người khác nghĩ rằng có cột đó là một sự lãng phí ngớ ngẩn của không gian.

Chúng tôi gặp nhau trong một vài ván đấm bốc ở một quán bar ở New Jersey vài tháng một lần.

+3

Tôi đồng ý rằng một danh tính hàng có thể đến khá tiện dụng, đặc biệt là nếu có bao giờ đến một thời điểm khi bạn cần một sự điều chỉnh trực tiếp đến sự tương quan. 1 cho boxing đấm bốc, quy tắc đầu tiên của DBA Fight Club ... – CAbbott

+2

@ hỗn loạn @ độc đáo đặt. Tôi thích thứ hai nhưng vẫn lên bầu bạn. Mỏ bia, cảm ơn :) – onedaywhen

+1

Nó có thể đáng chú ý Khuôn khổ thực thể xử lý bảng PK'less interesect khác với một bảng PKN – hanzolo

4

Những gì bạn đang xây dựng được gọi là "Giao lộ".

Tôi có một trí nhớ rất rõ ràng về giáo sư cơ sở dữ liệu của tôi ở trường nói rằng mối quan hệ giao nhau gần như luôn luôn là một thực thể theo đúng nghĩa của nó, và vì vậy nó thường có giá trị phân bổ không gian cho nó. Điều này sẽ chỉ ra rằng trước đây là "đúng" hơn.

Điều đó nói rằng, cá nhân tôi có xu hướng thích cái sau. Nó thực sự đi xuống cho dù bạn sẽ bao giờ lấy một trong những hồ sơ trực tiếp hoặc nếu bạn sẽ chỉ sử dụng bảng khi tham gia vào một trong các bảng ban đầu.

+0

bạn đã đưa ra một điểm tuyệt vời ... Tôi nghĩ những gì giáo sư nói có ý nghĩa với tôi. – Sung

3

Từ góc độ phối cảnh của nhà phát triển, tôi thích cái cũ hơn. Viết và kiểm tra dễ dàng hơn khi xử lý nó.

Tôi không cần kiểm tra hai khóa để truy lục bản ghi duy nhất.

4

nếu bạn đi đầu tiên, chỉ cần sử dụng IDENTITY trên PK, bạn không cần phải lãng phí dung lượng (đĩa và bộ nhớ cache) bằng UNIQUEIDENTIFIER.

+0

+1: điểm tốt, KM – van

3

Nếu bạn không có bất kỳ trường bổ sung nào trong bảng giao lộ, nó thực sự không cần ID của riêng nó và việc thêm một trường không thêm bất kỳ lợi ích nào. Tuy nhiên, nếu bạn định đặt các trường khác vào bảng đó và trong nhiều trường hợp, bạn sẽ có ID riêng làm khóa chính.

Quy tắc ngón tay cái, tất nhiên, nhưng bạn sẽ đến.

+0

Tại sao nó phải có ID vì các cột khác được thêm vào? –

+2

Bởi vì nó đột nhiên là một mục theo đúng nghĩa của nó, và bạn có thể cần phải tham khảo nó một cách dễ dàng. Không có bảng * yêu cầu * một ID, nó chỉ là một điều tiện dụng để có. Như tôi đã nói, quy tắc của ngón cái. –

1

Lợi ích của người đầu tiên:

Khả năng nhìn lên bảng tham gia bằng một giá trị duy nhất. Điều này làm cho một số hoạt động tìm kiếm đơn giản hơn ở phía khách hàng.

Một số ORM (NHibernate) cũng yêu cầu id trong mỗi thực thể để duy trì hoạt động bình thường.

Lợi ích của điều thứ hai:

đơn giản mô hình dữ liệu, mà không cần phải tạo ra các chỉ số bổ sung.

Ít bộ nhớ hơn.

1

Thứ hai là tốt hơn. Nó hạn chế hộp nối (hộp giao lộ) để không có nhiều hơn một ngoại hình của cùng một cặp. Nếu không có cột nào khác trong hộp nối, bạn sẽ không thực hiện tra cứu bảng này, ngoại trừ bằng cách nhấn hai phím ngoài.

+0

Cái đầu tiên cũng là "UNIQUE CONSTRAINT IX_Intersection UNIQUE (TableAId, TableBId") –

0

Cho rằng kết hợp TableAId-TableBId là duy nhất và bảng được sử dụng chỉ để thực hiện mối quan hệ nhiều-nhiều, tôi sẽ đi với tùy chọn thứ hai. Từ một quan điểm hoàn toàn hợp lý, việc nắm bắt nắm tay lại giảm xuống mức thứ hai. Từ quan điểm cấu trúc, các cơ sở dữ liệu của bạn cần duy trì cả khóa/chỉ mục chính cũng như ràng buộc trong việc triển khai thực hiện lần đầu tiên vào thứ hai, nó chỉ cần duy trì khóa/chỉ mục chính.

10

Sử dụng phiên bản 1 nếu "ngã tư" của bạn thực sự là một thực thể riêng của nó, có nghĩa là:

  • nó có thuộc tính bổ sung
  • bạn có thể tìm kiếm những đối tượng (và không phải điều hướng một mối quan hệ)

Người dùng phiên bản-2 nếu đó chỉ là bảng quan hệ NM. Trong trường hợp này cũng đảm bảo rằng:

  • bạn có PK của bạn (Clustered) với cột đầu tiên liên quan đến bảng tìm kiếm của bạn thường xuyên hơn: ví dụ nếu bảng của bạn là Person-Address, sau đó tôi sẽ cho rằng bạn sẽ tìm kiếm tất cả địa chỉ của một người thường xuyên hơn sau đó cho tất cả mọi người tại địa chỉ này. Vì vậy, bạn nên đặt PK của bạn để bao gồm PersonID đầu tiên
  • bạn vẫn có thể có một định danh duy nhất một cột, nhưng chỉ:

    1. hoặc là không làm cho nó một PK
    2. hoặc làm cho nó một PK, nhưng rõ NON Clustered, do đó bạn có thể sử dụng nhóm cho chỉ số UNIQUE bao gồm hai cột tham khảo
    3. trừ khi bạn sử dụng GUIDs bởi thiết kế của bạn, sau đó bạn có thể dính vào INT loại cột IDENTITY

Trong cả hai trường hợp, bạn có thể muốn tạo một INDEX khác bao gồm 2 cột, nhưng theo thứ tự khác, nếu bạn tìm kiếm từ phía bên kia của quan hệ thường xuyên.

3

Trả lời câu hỏi thứ hai của bạn ...

Bạn chỉ cần thêm một hạn chế kiểm tra, như thế này:

CREATE TABLE SomeIntersection 
(
    ParentRecord INT REFERENCES TableA NOT NULL, 
    ChildRecord INT REFERENCES TableA NOT NULL, 
    PRIMARY KEY(TableAId, TableBId), 
    CHECK (ParentRecord <> ChildRecord) 
) 
Các vấn đề liên quan