2010-10-22 43 views
5

Câu hỏi này đã xuất hiện một vài lần trong các diễn đàn khác nhau trong tìm kiếm của tôi, nhưng không có bảng nào cung cấp độ phân giải ngắn gọn.Bảng cơ sở dữ liệu, một bảng tham chiếu nhiều bảng không liên quan

Nếu tôi có các bảng sau:

User 
+- id 
+- username 
+- password 

Article 
+- id 
+- title 
+- content 

và tôi muốn tham gia cùng họ để xác định người đã tạo ra những gì bài báo, tôi chỉ đơn giản có thể thêm cột user_id để Điều để sử dụng như một tài liệu tham khảo. Ngoài ra, tôi sẽ thêm một bảng trung gian để hiển thị ai/khi nào/cái gì, ví dụ:

User 
+- ... 

Article 
+- ... 

ChangeHistory 
+- id 
+- article_id 
+- user_id 
+- type [enum(insert, update, delete)] 
+- datetime 

Bây giờ điều này là tốt, nhưng hệ thống tôi đang làm việc cần phải năng động hơn nhiều, trong đó mô-đun có thể dễ dàng được giới thiệu và tích hợp. Vì vậy, bây giờ nếu tôi thêm một phương tiện bảng tôi cần phải chia ChangeHistory giữa ĐiềuTruyền thông có:

User 
+- ... 

Article 
+- ... 

Media 
+- id 
+- title 
+- path 

ArticleChangeHistory 
+- id 
+- article_id 
+- user_id 
+- type [enum(insert, update, delete)] 
+- datetime 

MediaChangeHistory 
+- id 
+- media_id 
+- user_id 
+- type [enum(insert, update, delete)] 
+- datetime 

này có thể thoát khỏi tay một cách nhanh chóng với sự ra đời của nhiều mô-đun. Mỗi mô-đun sẽ cần phải chịu trách nhiệm về việc tạo và quản lý riêng bảng ChangeHistory của riêng nó.

TL; DR: Tôi có thể khám phá những phương pháp nào để tạo bảng trung gian có thể nhận tham chiếu đến nhiều bảng không liên quan khác? Tôi có thể thêm một trường * record_type *, giữ tên của bảng mà bản ghi đó thuộc về, nhưng đó là xấu. Tôi sẽ cần một thứ gì đó như "ID bảng " để tham chiếu bảng mà từ đó nó đến. Bằng cách đó, khi/nếu các mô-đun được thêm vào hoặc bị loại bỏ, mô hình không bị phân tách.

Bất kỳ ý tưởng nào? Cảm ơn rất nhiều trước.

+0

Có một số lý do khiến bạn coi "ID bảng" phải tốt hơn "record_type" không? –

Trả lời

4

Theo kinh nghiệm của tôi, khi các nhà phát triển cố gắng làm cho hệ thống của họ thực sự "năng động", họ đang thực sự cố gắng để viết mã cho các vấn đề mà họ đã không nghĩ đến được nêu ra. Đó thường là một con đường xấu để có. Có thực sự là quá nhiều công việc cho một mô-đun để bao gồm hai bảng thay vì một?

Trong mọi trường hợp tôi đã thấy mẫu (hoặc chống mẫu?) Cố gắng tạo ra một bảng "làm mọi thứ" chung chung, nó rơi phẳng trên khuôn mặt của nó. RDBMS hoạt động tốt nhất với các khu vực có vấn đề được xác định rõ. Nếu mô-đun có nhu cầu lưu giữ lịch sử thì mô-đun sẽ thêm một bảng lịch sử để đi với chính bảng đó. Điều này cũng có một lợi thế rất lớn trong đó xuống con đường bạn có thể muốn giữ các loại thông tin khác nhau trong lịch sử tùy thuộc vào bảng hoặc mô-đun mà lịch sử đang được lưu giữ. Nếu bạn có một bảng lịch sử chung chung trở nên khó khăn hơn nhiều.

Bây giờ, nếu bạn muốn chỉ cần chụp người dùng cuối để cập nhật hoặc chèn một mục cụ thể (hàng bảng) và có thể ở nhiều bảng thì bạn có thể sử dụng mẫu thừa kế trong đó bạn có bảng cha và nhiều con những cái bàn. Ví dụ:

CREATE TABLE Audited_Items 
(
    id INT NOT NULL IDENTITY, 
    CONSTRAINT PK_Audited_Items PRIMARY KEY CLUSTERED (id) 
) 
CREATE TABLE Articles 
(
    id INT   NOT NULL, 
    [Article specific columns] 
    CONSTRAINT PK_Articles PRIMARY KEY CLUSTERED (id), 
    CONSTRAINT FK_Articles_Audited_Items FOREIGN KEY (id) REFERENCES Audited_Items (id) 
) 
CREATE TABLE Media 
(
    id INT   NOT NULL, 
    [Media specific columns] 
    CONSTRAINT PK_Media PRIMARY KEY CLUSTERED (id), 
    CONSTRAINT FK_Media_Audited_Items FOREIGN KEY (id) REFERENCES Audited_Items (id) 
) 
CREATE TABLE Audit_Trail 
(
    audited_item_id INT   NOT NULL, 
    audit_datetime  DATETIME NOT NULL, 
    user_id   INT   NOT NULL, 
    [audit columns] 
    CONSTRAINT PK_Audit_Trail PRIMARY KEY CLUSTERED (audited_item_id, audit_datetime), 
    CONSTRAINT FK_Audit_Trail_Audited_Items FOREIGN KEY (audited_item_id) REFERENCES Audited_Items (id) 
) 
+0

Cảm ơn bạn đã phản hồi chi tiết Tom. Tôi rất thích thiết kế này và tôi sẽ xem xét nó trong nghiên cứu sâu hơn của mình. – Dan

+0

Đóng vòng lặp cho câu hỏi, cảm ơn Tom H., phương pháp của bạn dường như đáp ứng được thiết kế của tôi khá tốt. Hy vọng rằng ít thay đổi sẽ cần phải được thực hiện xuống đường. – Dan

2

Dường như với tôi bạn đang yêu cầu hướng dẫn dẫn bạn xuống một con đường ngoằn ngoèo, xoắn ốc.

Tôi không biết tại sao bạn cần phải thêm một bảng mới mỗi khi bạn nhận được một "mô-đun" mới (không rõ ràng cho tôi mô-đun là gì) miễn là các mô-đun có thể được mô tả với cùng một bố cục cột . Bạn có thể thêm một bảng Mô-đun và sau đó bao gồm một cột ModuleId trong bảng Các bài viết.

Ngoài ra, các bài viết có thể có nhiều hơn một tác giả, vì vậy nếu bạn làm, bạn cần một bảng ArticleAuthors. Và trong một số vòng kết nối, thứ tự của các tác giả trên một bài viết là rất quan trọng. Đó là một thứ hạng tầm quan trọng của sự đóng góp của họ hoặc tầm quan trọng của họ trong lĩnh vực này. Nếu đúng như vậy, bạn cần có cột "thứ tự" để phản ánh vị trí của tác giả.

+0

Cảm ơn bạn đã phản hồi nhanh Tim; Các mô-đun đại diện cho các hệ thống con của CMS mà tôi đang làm việc. Nhiều tác giả của một bài viết có thể được đại diện bởi tác giả gốc Tác giả và các chỉnh sửa tác giả tiếp theo. Người dùng được xếp hạng theo cấp độ (Tôi không bao gồm nhiều trường không liên quan trong các mẫu ví dụ của tôi vì mục đích đơn giản) Tôi đã hy vọng tìm thấy một số giải pháp "bảng ID", độc lập với chính mô hình ... – Dan

+1

Để mở rộng thêm một chút, tôi có một bảng Modules, để đăng ký và hủy đăng ký module (và giữ cấu hình params, vv) nhưng một Module có thể có nhiều bảng, như Discography with Track và Album. Cả Track và Album sẽ cần các bảng ChangeHistory riêng lẻ (hoặc các tham chiếu trong một bảng trung gian chung) và do đó một mô đun duy nhất sẽ không đủ để tham chiếu cả Bản nhạc và Album. – Dan

2

Tôi nghĩ rằng bạn có thể giảm giá tốt nhất với một bảng ChangeHistory duy nhất mà trông giống như sau: (. Ví dụ như bài báo, phương tiện truyền thông, vv ...)

 
ItemChangeHistory 
+- id 
+- changedItem_id 
+- user_id 
+- changedItemType_id 
+- type [enum(insert, update, delete)] 
+- datetime 

và sau đó sử dụng changedItemType_id để tìm ra những gì đã được thay đổi dựa trên bảng itemType. Bằng cách này, bạn chỉ có một bảng cho tất cả lịch sử thay đổi nội dung và bạn không phải thêm/xóa bảng khi bạn thêm/xóa mô-đun, bạn chỉ cần cập nhật bảng itemType.Tất nhiên điều này có nghĩa rằng việc loại bỏ một mô-đun phải được thực hiện cẩn thận - bạn có thể để lại các bản ghi ItemChangeHistory tham chiếu đến loại mô-đun đó (nhưng đó là lộn xộn) hoặc xóa tất cả lịch sử được liên kết với mô-đun.


Bây giờ bạn có đề cập đến một mô-đun có thể có các bảng khác, như vậy có lẽ những người cần phải được theo dõi với một ID submodule, cũng được tham chiếu trong ItemChangeHistory?

0

Tại sao không

ChangeHistory 
+- id 
+- content_id 
+- content_type 
+- user_id 
+- action [enum(added, updated, deleted)] 
+- datetime 
0

@Majid: Tôi hiểu rằng có khả năng là giải pháp hợp lý nhất, nhưng tôi đã hy vọng để tìm thấy một cái gì đó một chút trực quan hơn, một cái gì đó có khả năng có thể tận dụng lợi thế của các thông số DB hiện có; chẳng hạn như id bảng khó nắm bắt (và rõ ràng không tồn tại) (do đó tôi có nghĩa là một số loại tham chiếu nội bộ mà động cơ, InnoDB trong trường hợp của tôi, sử dụng để mô tả bảng)

@frustrated: Tôi cho rằng sẽ đi với một cái gì đó như thế. Tôi sẽ tiếp tục điều tra khả năng.

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