2009-03-21 42 views
81

Tôi có hai bảng là employee_ce và employees_sn theo nhân viên cơ sở dữ liệu.Khóa nước ngoài đề cập đến các khóa chính trên nhiều bảng?

Cả hai đều có cột khóa chính duy nhất tương ứng.

Tôi có một bảng khác được gọi là khoản khấu trừ, có cột khóa ngoài tôi muốn tham chiếu đến khóa chính của employees_ce cũng như employees_sn. Điều này có thể không?

ví dụ

employees_ce 
-------------- 
empid name 
khce1 prince 

employees_sn 
---------------- 
empid name 
khsn1 princess 

như vậy là điều này có thể?

deductions 
-------------- 
id  name 
khce1 gold 
khsn1 silver 

Trả lời

2

Về mặt kỹ thuật có thể. Bạn có thể tham khảo employee_ce trong các khoản khấu trừ và employees_sn. Nhưng tại sao bạn không hợp nhất employees_sn và employees_ce? Tôi thấy không có lý do tại sao bạn có hai bảng. Không ai quan hệ nhiều. Và (không phải trong ví dụ này) nhiều cột.

Nếu bạn thực hiện hai tham chiếu cho một cột, một nhân viên phải có mục nhập trong cả hai bảng.

1

Có, điều đó là có thể. Bạn sẽ cần phải xác định 2 FK cho bảng thứ 3. Mỗi FK trỏ đến (các) trường bắt buộc của một bảng (tức là 1 FK cho mỗi bảng nước ngoài).

21

Bạn có thể thêm hai ràng buộc khóa ngoài (trung thực: tôi chưa bao giờ thử), nhưng sau đó nó sẽ nhấn mạnh hàng gốc tồn tại trong cả hai bảng.

Thay vào đó, bạn có thể muốn tạo siêu kiểu cho hai loại phụ của nhân viên, sau đó chỉ định khóa ngoại ở đó. (Giả sử bạn có một lý do chính đáng để chia hai loại nhân viên, tất nhiên).

    employee  
employees_ce  ————————  employees_sn 
————————————  type   ———————————— 
empid —————————> empid <——————— empid 
name    /|\   name 
        | 
        | 
     deductions | 
     —————————— | 
     empid ————————+ 
     name 

type trong bảng nhân viên sẽ ce hoặc sn.

+0

tôi đã cố gắng thêm nhiều phím nước ngoài, họ làm việc nhưng, trong khi thêm một kỷ lục, derby java nói với tôi cả hai khó khăn chính nước ngoài đã bị vi phạm! –

+0

Tôi vừa thử nó trên PostgreSQL, và nó hoạt động ở đó. Bạn có hồ sơ gốc trong cả hai bảng? – derobert

+0

bản ghi cha mẹ bạn muốn nói, là sự hỗ trợ? –

87

Giả sử rằng tôi đã hiểu kịch bản của bạn một cách chính xác, đây là những gì tôi sẽ gọi đúng cách để làm điều này:

Bắt đầu từ một mô tả cấp cao của cơ sở dữ liệu của bạn! Bạn có nhân viên, và nhân viên có thể là nhân viên "ce" và nhân viên "sn" (dù họ là ai). Trong các thuật ngữ hướng đối tượng, có một "nhân viên" lớp, với hai lớp con được gọi là "nhân viên ce" và "nhân viên sn".

Sau đó bạn dịch mô tả này cấp trên cho ba bảng: employees, employees_ceemployees_sn:

  • employees(id, name)
  • employees_ce(id, ce-specific stuff)
  • employees_sn(id, sn-specific stuff)

Vì tất cả các nhân viên là nhân viên (duh !), mọi nhân viên sẽ có một hàng trong số employees bàn. Nhân viên "ce" cũng có một hàng trong bảng employees_ce và nhân viên "sn" cũng có một hàng trong bảng employees_sn. employees_ce.id là khóa ngoài của employees.id, giống như employees_sn.id.

Để chỉ người lao động thuộc loại nào (ce hoặc sn), hãy tham khảo bảng employees. Đó là, chìa khóa nước ngoài bạn gặp rắc rối với nên tham khảo bảng đó!

+12

Làm thế nào để bạn thực hiện ce và sn loại trừ lẫn nhau? Vì một nhân viên không thể đồng thời là ce và sn, nên thực hành tốt để phản ánh điều đó trong cơ sở dữ liệu. Tôi đang gặp sự cố này ngay bây giờ. – Rolf

+0

Tôi nghĩ rằng nhiều phím cột có thể giúp giải quyết vấn đề trong nhận xét trước của tôi ... tìm kiếm ngay bây giờ. – Rolf

+12

Bạn có thể buộc nhân viên chỉ ở trong một bảng (và bảng đúng) bằng cách lưu trữ một loại trong bảng cơ sở cũng như các bảng dẫn xuất. Tạo id khóa chính, khóa duy nhất trên (id, type), khóa ngoài của bảng con được bật (id, type) và đặt ràng buộc CHECK trên mỗi bảng con để chỉ có đúng loại. Hoặc, nếu cơ sở dữ liệu của bạn thực hiện các ràng buộc kiểm tra toàn cầu (và không có hình phạt tốc độ lớn), bạn có thể chỉ cần thực hiện kiểm tra NOT EXISTS. – derobert

0

Giả sử bạn phải có hai bảng cho hai loại người lao động đối với một số lý do, tôi sẽ mở rộng về câu trả lời vmarquez của:

Schema:

employees_ce (id, name) 
employees_sn (id, name) 
deductions (id, parentId, parentType, name) 

dữ liệu trong khấu trừ:

deductions table 
id  parentId  parentType  name 
1  1    ce    gold 
2  1    sn    silver 
3  2    sn    wood 
... 

Điều này sẽ cho phép bạn khấu trừ điểm cho bất kỳ bảng nào khác trong lược đồ của bạn. Loại quan hệ này không được hỗ trợ bởi các ràng buộc mức cơ sở dữ liệu, IIRC do đó bạn sẽ phải đảm bảo rằng ứng dụng của bạn quản lý ràng buộc đúng cách (điều này làm cho nó trở nên cồng kềnh hơn nếu bạn có nhiều ứng dụng/dịch vụ khác nhau cùng cơ sở dữ liệu).

15

Thực ra tôi tự làm điều này. Tôi có một bảng gọi là 'Bình luận' trong đó có ý kiến ​​cho các bản ghi trong 3 bảng khác. Không giải pháp nào thực sự xử lý mọi thứ bạn có thể muốn. Trong trường hợp của bạn, bạn sẽ làm điều này:

Giải pháp 1:

  1. Thêm một lĩnh vực tinyint để employees_ce và employees_sn mà có một giá trị mặc định đó là khác nhau trong mỗi bảng (Trường này đại diện cho một ' định danh bảng ', vì vậy chúng tôi sẽ gọi chúng là tid_ce & tid_sn)

  2. Tạo chỉ mục duy nhất trên mỗi bảng bằng cách sử dụng trường của bảng và trường id bảng.

  3. Thêm một lĩnh vực tinyint để bàn 'Trích' của bạn để lưu trữ vào nửa cuối của khóa ngoại (Biểu ID)

  4. Tạo 2 phím nước ngoài trong bảng 'Trích' của bạn (Bạn không thể thi hành tham chiếu toàn vẹn, bởi vì hoặc là một chìa khóa sẽ có giá trị này hay cách khác ... nhưng không bao giờ cả:

    ALTER TABLE [dbo].[Deductions] WITH NOCHECK ADD CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid]) 
    REFERENCES [dbo].[employees_ce] ([empid], [tid]) 
    NOT FOR REPLICATION 
    GO 
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_ce] 
    GO 
    ALTER TABLE [dbo].[Deductions] WITH NOCHECK ADD CONSTRAINT [FK_Deductions_employees_sn] FOREIGN KEY([id], [fk_tid]) 
    REFERENCES [dbo].[employees_sn] ([empid], [tid]) 
    NOT FOR REPLICATION 
    GO 
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn] 
    GO 
    
    employees_ce 
    -------------- 
    empid name  tid 
    khce1 prince 1 
    
    employees_sn 
    ---------------- 
    empid name  tid 
    khsn1 princess 2 
    
    deductions 
    ---------------------- 
    id  tid  name 
    khce1 1   gold 
    khsn1 2   silver   
    ** id + tid creates a unique index ** 
    

giải pháp 2: giải pháp này cho phép toàn vẹn tham chiếu là ma intained: 1. Tạo một lĩnh vực trọng điểm nước ngoài thứ hai trong bảng 'Trích', cho phép giá trị Null trong cả hai phím nước ngoài, và tạo ra các phím nước ngoài bình thường:

employees_ce 
    -------------- 
    empid name 
    khce1 prince 

    employees_sn 
    ---------------- 
    empid name  
    khsn1 princess 

    deductions 
    ---------------------- 
    idce idsn  name 
    khce1 *NULL* gold 
    *NULL* khsn1  silver   

Liêm chỉ được kiểm tra nếu cột không phải là null, vì vậy bạn có thể duy trì tính toàn vẹn tham chiếu.

6

Tôi biết đây là chủ đề trì trệ lâu, nhưng trong trường hợp bất kỳ ai tìm kiếm ở đây là cách tôi xử lý các khóa ngoại bảng đa. Với kỹ thuật này, bạn không có bất kỳ hoạt động thác tầng nào được thực thi bởi DBA, vì vậy hãy đảm bảo bạn xử lý DELETE và các mã như vậy trong mã của bạn.

Table 1 Fruit 
pk_fruitid, name 
1, apple 
2, pear 

Table 2 Meat 
Pk_meatid, name 
1, beef 
2, chicken 

Table 3 Entity's 
PK_entityid, anme 
1, fruit 
2, meat 
3, desert 

Table 4 Basket (Table using fk_s) 
PK_basketid, fk_entityid, pseudo_entityrow 
1, 2, 2 (Chicken - entity denotes meat table, pseudokey denotes row in indictaed table) 
2, 1, 1 (Apple) 
3, 1, 2 (pear) 
4, 3, 1 (cheesecake) 

SO Ví dụ Op của sẽ trông như thế này

deductions 
-------------- 
type id  name 
1  khce1 gold 
2  khsn1 silver 

types 
--------------------- 
1 employees_ce 
2 employees_sn 
Các vấn đề liên quan