2009-07-24 33 views
6

Hi Im đang vật lộn một chút với điều này và có thể sử dụng một số ý tưởng ...Bản ghi được liên kết với bất kỳ bảng nào?

Nói cơ sở dữ liệu của tôi có các bảng sau; Khách hàng supplers SalesInvoices PurchaseInvoices Đơn vị tiền tệ

vv vv

Tôi muốn để có thể thêm một "Notes" kỷ lục để bất kỳ loại hồ sơ

Các Thuyết minh bảng muốn

này
NoteID  Int (PK) 
NoteFK  Int 
NoteFKType Varchar(3) 
NoteText  varchar(100) 
NoteDate  Datetime 

Nơi lưu ýFK là PK của khách hàng hoặc nhà cung cấp v.v. và NoteFKType cho biết loại reco nào ghi chú là chống lại

Bây giờ tôi nhận ra rằng tôi không thể thêm một FK tham chiếu nhiều bảng mà không cần NoteFK cần có mặt trong tất cả các bảng.

Vậy bạn sẽ thiết kế như thế nào ở trên? Những lưu ý FK cần phải được trong bất kỳ các bảng trên

Chúc mừng, Daniel

+0

Yêu cầu tính toàn vẹn tham chiếu cấp cơ sở dữ liệu hay bạn có thể sống với tính toàn vẹn tham chiếu được quản lý của ứng dụng không? – tschaible

Trả lời

-2

Tại sao không bạn làm điều đó theo cách khác xung quanh và có một phím nước ngoài trong các bảng khác (khách hàng, nhà cung cấp vv vv) để NotesID. Bằng cách này bạn có một bản đồ.

+1

Nếu anh ta muốn có mối quan hệ một-nhiều thì sao? Nhiều ghi chú cho một thực thể.Anh ta sẽ kết thúc với nhiều bảng bổ sung không cần thiết. – maciejkow

+1

Điều này sẽ không đảm bảo rằng cùng một NoteID không được tham chiếu nhiều lần. Nhưng điều đó phụ thuộc vào yêu cầu kinh doanh. –

+0

Nếu có nhu cầu từ một đến nhiều, chúng tôi có thể lưu trữ các ghi chú được phân cách bằng dấu phẩy (đây chỉ là giải pháp thay thế) thay vì có các bảng khác nhau để liên kết. –

0

Bạn có thể thêm trường GUID vào bảng Khách hàng, Nhà cung cấp, v.v. Sau đó trong bảng ghi chú, thay đổi khóa ngoại để tham chiếu GUID đó.

Điều này không giúp tính toàn vẹn dữ liệu. Nhưng nó làm cho mối quan hệ M-to-N dễ dàng có thể với bất kỳ số lượng bảng nào và nó giúp bạn không phải xác định cột NoteFKType trong bảng Ghi chú.

2

Tôi nghĩ thiết kế của bạn là ok, nếu bạn có thể chấp nhận thực tế, hệ thống db sẽ không kiểm tra xem một ghi chú có tham chiếu đến thực thể hiện có trong bảng khác hay không. Đó là thiết kế duy nhất tôi có thể nghĩ về điều đó không đòi hỏi phải sao chép và có thể mở rộng đến nhiều bảng hơn.

Cách bạn thiết kế, khi bạn thêm một loại đối tượng khác mà bạn muốn có ghi chú, bạn sẽ không phải thay đổi mô hình của mình. Ngoài ra, bạn không phải bao gồm bất kỳ cột bổ sung nào trong mô hình hiện tại của mình hoặc các bảng bổ sung.

Để đảm bảo tính toàn vẹn dữ liệu, bạn có thể tạo bộ kích hoạt hoặc một số giải pháp phần mềm sẽ làm sạch bảng ghi chú một lần trong một thời gian.

3

Bạn phải chấp nhận giới hạn mà bạn không thể dạy cơ sở dữ liệu về ràng buộc khóa ngoại này. Vì vậy, bạn sẽ phải làm mà không kiểm tra tính toàn vẹn (và tầng xóa).

Thiết kế của bạn tốt. Có thể mở rộng dễ dàng các bảng phụ, bạn có thể có nhiều ghi chú cho mỗi thực thể và các bảng đích thậm chí không cần phải biết tính năng ghi chú.

Lợi thế mà thiết kế này sử dụng bảng ghi chú riêng cho mỗi bảng thực thể là bạn có thể dễ dàng chạy truy vấn trên tất cả ghi chú, ví dụ: "ghi chú gần đây nhất" hoặc "tất cả ghi chú do người dùng đã tạo".

Đối với đối số của bảng phát triển quá lớn, chia nó thành năm bảng sẽ thu nhỏ bảng xuống khoảng 1/5 kích thước của nó, nhưng điều này sẽ không tạo ra bất kỳ sự khác biệt nào cho truy cập dựa trên chỉ mục. Cơ sở dữ liệu được xây dựng để xử lý các bảng lớn (miễn là chúng được lập chỉ mục đúng).

0

Bạn có thể dễ dàng triển khai khóa "đa" ở bên ngoài bằng trình kích hoạt. Trình kích hoạt sẽ cung cấp cho bạn cơ chế rất linh hoạt và bạn có thể thực hiện bất kỳ kiểm tra tính toàn vẹn nào mà bạn muốn.

1

Tôi sẽ suy nghĩ kỹ trước khi thực hiện những gì bạn đề xuất. Nó có vẻ đơn giản và thanh lịch trong ngắn hạn, nhưng nếu bạn thực sự quan tâm đến tính toàn vẹn dữ liệu và hiệu năng, thì có các bảng ghi chú riêng biệt cho mỗi bảng cha là cách để đi. Trong những năm qua, tôi đã tiếp cận vấn đề này bằng cách sử dụng các giải pháp tìm thấy trong các câu trả lời khác (gây nên, GUIDs, vv). Tôi đã đi đến kết luận rằng sự phức tạp và mất hiệu suất được thêm vào không phải là giá trị nó. Bằng cách có các bảng ghi chú riêng biệt cho mỗi bảng cha, với một ràng buộc khóa ngoài thích hợp, tra cứu và kết nối sẽ đơn giản và nhanh chóng. Khi kết hợp các mục có liên quan vào một bảng, cú pháp tham gia trở nên xấu xí và bảng ghi chú của bạn sẽ phát triển rất lớn và chậm.

+0

+1 Tôi đồng ý và có thể xác minh điều này. Về lâu dài, bạn chỉ làm phức tạp giải pháp của bạn và thêm nợ kỹ thuật mà cuối cùng sẽ cần phải được xử lý. –

+0

Mặt khác, anh ta có thể với các giải pháp chạy truy vấn hiện tại của mình trên tất cả các ghi chú, điều này sẽ khó khăn với nhiều bảng ghi chú. – Thilo

+1

@Thilo - Với lời khuyên của Michael trong đầu, SQL View là cách thích hợp hơn để tổng hợp tất cả các bảng ghi chú thành một nguồn truy vấn đơn lẻ. –

1

Tôi đồng ý với Michael McLosky, ở một mức độ.

Câu hỏi trong đầu tôi là: Chi phí kỹ thuật của việc có nhiều bảng ghi chú là gì?

Trong suy nghĩ của tôi, Tốt hơn là nên hợp nhất cùng một chức năng vào một bảng. Nó làm cho báo cáo và phát triển hơn nữa đơn giản hơn. Chưa kể đến việc giữ danh sách các bảng nhỏ hơn và dễ quản lý hơn.

Đó là một hành động cân bằng, bạn cần phải cố gắng xác định trước cả lợi ích và chi phí làm một cái gì đó như thế này. Tùy chọn -personal- của tôi là toàn vẹn tham chiếu cơ sở dữ liệu. Ứng dụng quản lý tính toàn vẹn nên, theo ý kiến ​​của tôi, được giới hạn ot logic kinh doanh. Cơ sở dữ liệu nên đảm bảo dữ liệu luôn luôn là nhất quán và hợp lệ ...


Để thực sự trả lời câu hỏi của bạn ...

Tùy chọn Tôi sẽ sử dụng là một hạn chế kiểm tra sử dụng một User Defined Chức năng kiểm tra các giá trị. Điều này hoạt động trong M $ SQL Server ...

CREATE TABLE Test_Table_1 (id INT IDENTITY(1,1), val INT) 
GO 
CREATE TABLE Test_Table_2 (id INT IDENTITY(1,1), val INT) 
GO 
CREATE TABLE Test_Table_3 (fk_id INT, table_name VARCHAR(64)) 
GO 

CREATE FUNCTION id_exists (@id INT, @table_name VARCHAR(64)) 
RETURNS INT 
AS 
BEGIN 
    IF (@table_name = 'Test_Table_1') 
     IF EXISTS(SELECT * FROM Test_Table_1 WHERE id = @id) 
      RETURN 1 
    ELSE 
    IF (@table_name = 'Test_Table_2') 
     IF EXISTS(SELECT * FROM Test_Table_2 WHERE id = @id) 
      RETURN 1 

    RETURN 0 
END 
GO 

ALTER TABLE Test_Table_3 WITH CHECK ADD CONSTRAINT 
    CK_Test_Table_3 CHECK ((dbo.id_exists(fk_id,table_name)=(1))) 
GO 
ALTER TABLE [dbo].[Test_Table_3] CHECK CONSTRAINT [CK_Test_Table_3] 
GO 

INSERT INTO Test_Table_1 SELECT 1 
GO 
INSERT INTO Test_Table_1 SELECT 2 
GO 
INSERT INTO Test_Table_1 SELECT 3 
GO 
INSERT INTO Test_Table_2 SELECT 1 
GO 
INSERT INTO Test_Table_2 SELECT 2 
GO 
INSERT INTO Test_Table_3 SELECT 3, 'Test_Table_1' 
GO 
INSERT INTO Test_Table_3 SELECT 3, 'Test_Table_2' 
GO 

Trong ví dụ này, câu lệnh chèn cuối cùng sẽ thất bại.

1

Bạn có thể nhận được tính toàn vẹn tham chiếu FK, với chi phí có một cột trong bảng ghi chú cho mỗi bảng khác.

create table Notes (
    id int PRIMARY KEY, 
    note varchar (whatever), 
    customer_id int NULL REFERENCES Customer (id), 
    product_id int NULL REFERENCES Product (id) 
) 

Sau đó, bạn sẽ cần một ràng buộc để đảm bảo rằng bạn chỉ có một trong các cột được đặt.

Hoặc có thể không, có thể bạn có thể muốn ghi chú để có thể được liên kết với cả khách hàng và sản phẩm. Tùy thuộc vào bạn.

Thiết kế này sẽ yêu cầu thêm cột mới vào Ghi chú nếu bạn muốn thêm một bảng tham chiếu khác.

+0

Đó có lẽ là giải pháp thanh lịch nhất cho đến nay. – Thilo

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