2009-06-05 48 views
7

Loại thủ thuật sql nào bạn sử dụng để nhập dữ liệu vào hai bảng có tham chiếu vòng tròn ở giữa.Xử lý tham chiếu vòng tròn khi nhập dữ liệu trong SQL

Employees 
    EmployeeID <PK> 
    DepartmentID <FK> NOT NULL 

Departments 
    DepartmentID <PK> 
    EmployeeID <FK> NOT NULL 

Nhân viên thuộc phòng ban, bộ phận phải có người quản lý (trưởng phòng).

Tôi có phải tắt các ràng buộc cho việc chèn xảy ra không?

+0

Điều này có vẻ giống như một sơ đồ xa lạ với tôi, bạn có thể giải thích lý do tại sao bạn có mối quan hệ theo cách này? – Bob

+3

Có phải EmployeeId trong bảng phân công của bạn giống như một người quản lý bộ phận hay không? –

+0

Trong Oracle, "thủ thuật" là xác định khoá ngoại (DEFERRABLE). – spencer7593

Trả lời

5

Q: Tôi có phải tắt các ràng buộc cho việc chèn xảy ra không?
A: Trong Oracle, không, không phải nếu ràng buộc khoá ngoại là DEFERRABLE (xem ví dụ dưới đây)

Đối với Oracle:

 
    SET CONSTRAINTS ALL DEFERRED; 
    INSERT INTO Departments values ('foo','dummy'); 
    INSERT INTO Employees values ('bar','foo'); 
    UPDATE Departments SET EmployeeID = 'bar' WHERE DepartmentID = 'foo'; 
    COMMIT; 

Hãy giải nén rằng:

  • (phải tự động tắt)
  • trì hoãn việc thực thi ràng buộc khóa ngoài
  • chèn một hàng để bảng cục với một "dummy" giá trị cho cột FK
  • chèn một hàng để bảng Employee với FK tham chiếu đến cục
  • thay thế "dummy" giá trị tại Khoa FK với tài liệu tham khảo thực
  • bật lại thi hành những hạn chế

GHI CHÚ: vô hiệu hóa một ràng buộc khoá ngoại có hiệu lực cho tất cả các phiên, trì hoãn một hạn chế là ở mức độ giao dịch (như trong ví dụ), hoặc ở cấp phiên (ALTER SESSION SET CONSTRAINTS=DEFERRED;)

Oracle đã cho phép các ràng buộc khóa ngoài được định nghĩa là DEFERRABLE trong ít nhất một thập kỷ. Tôi xác định tất cả các ràng buộc khóa ngoại (như là một vấn đề của khóa học) là DEFERRABLE INITIALLY IMMEDIATE. Điều đó giữ cho hành vi mặc định như mọi người mong đợi, nhưng cho phép thao tác mà không yêu cầu khóa ngoài bị vô hiệu hóa.

thấy AskTom: http://www.oracle.com/technology/oramag/oracle/03-nov/o63asktom.html

thấy AskTom: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10954765239682

also see: http://www.idevelopment.info/data/Oracle/DBA_tips/Database_Administration/DBA_12.shtml

[EDIT]

A: Trong Microsoft SQL Server, bạn có thể không trì hoãn các ràng buộc khóa ngoại như bạn có thể trong Oracle. Việc vô hiệu hóa và kích hoạt lại ràng buộc khoá ngoại là một cách tiếp cận, nhưng tôi rùng mình trước viễn cảnh 1) tác động hiệu suất (ràng buộc khóa ngoài được kiểm tra cho bảng TOÀN BỘ khi ràng buộc được kích hoạt lại), 2) xử lý ngoại lệ nếu (khi nào?) việc kích hoạt lại ràng buộc không thành công. Lưu ý rằng việc vô hiệu hóa ràng buộc sẽ ảnh hưởng đến tất cả các phiên, do đó, trong khi ràng buộc bị vô hiệu hóa, các phiên khác có khả năng chèn và cập nhật các hàng sẽ gây ra sự ràng buộc của ràng buộc thất bại.

Với SQL Server, cách tiếp cận tốt hơn là xóa ràng buộc NOT NULL và cho phép NULL làm chỗ dành sẵn trong khi các hàng đang được chèn/cập nhật.

Đối với SQL Server:

 
    -- (with NOT NULL constraint removed from Departments.EmployeeID) 
    insert into Departments values ('foo',NULL) 
    go 
    insert into Employees values ('bar','foo') 
    go 
    update Departments set EmployeeID = 'bar' where DepartmentID = 'foo' 
    go 

[/ EDIT]

+1

Chỉ cần phát hiện ra rằng Sybase sẽ cho phép bạn làm điều đó quá với SET OPTION WAIT_FOR_COMMIT = 'ON'. Đặt nó thành BẬT sẽ trì hoãn việc kiểm tra tham chiếu cho đến khi bạn gọi COMMIT. TÙY CHỌN SET WAIT_FOR_COMMIT = 'ON'; chèn vào nhân viên ... chèn vào các phòng ban ... COMMIT; TÙY CHỌN SET WAIT_FOR_COMMIT = 'OFF'; Bây giờ chỉ thiếu MSSQL;) – Tom

+0

-1 "một cách tiếp cận tốt hơn là loại bỏ ràng buộc NOT NULL" - làm thế nào để bạn ngăn chặn "trình giữ chỗ tạm thời" còn lại vô thời hạn. – onedaywhen

+0

@Tom: cảm ơn vì lưu ý hữu ích, về việc bật "kiểm tra hạn chế trì hoãn" trên Sybase. – spencer7593

0

Có, trong trường hợp này, bạn sẽ phải tắt khóa ngoại.

1

Tái cấu trúc giản đồ bằng cách xóa tham chiếu vòng tròn.
Xóa cột ID khỏi một trong hai lược đồ bảng.

Departments.EmployeeID dường như không thuộc về ý kiến ​​của tôi.

1

Tôi không thể nghĩ ra một cách không hackish để làm điều này. Tôi nghĩ rằng bạn sẽ cần phải loại bỏ các ràng buộc hoặc làm một số loại giá trị giả ngớ ngẩn mà được cập nhật sau khi tất cả các chèn.

Tôi muốn khuyên bạn nên tái cấu trúc lược đồ DB. Tôi không thể nghĩ ra bất kỳ lý do nào khiến bạn muốn nó hoạt động theo cách này.

Có thể một cái gì đó như, Nhân viên, EmployeeDepartment (EmployeeId, DepartmentId) và Sở sẽ là một cách tốt hơn để thực hiện cùng một mục tiêu.

0

Bạn cần loại bỏ vĩnh viễn một hoặc một tham chiếu khác. Đây không phải là một cấu trúc thiết kế khả thi. Cái nào phải được nhập trước? Sở hoặc nhân viên? Trừ khi các phòng ban của bạn là tất cả một nhân viên lớn, cấu trúc không có ý nghĩa anyway vì mỗi nhân viên sẽ phải có một bộ phận riêng biệt.

+0

Tôi không lý do tại sao đó không phải là một cấu trúc thiết kế khả thi. Các nhân viên thuộc về một bộ phận, một bộ phận phải có một người quản lý (trưởng phòng). – Tom

+1

Không có phòng nào không phải có người quản lý. Các vị trí trưởng phòng bị bỏ trống. Nhưng nó không thể thực hiện được vì bạn không bao giờ có một tình huống pk/fk tròn và làm cho nó hoạt động với hacking để vượt qua các ràng buộc. Sự cần thiết phải hack để có được xung quanh những khó khăn là đầu mối đầu tiên của bạn rằng thiết kế là xấu. Tôi woul dhavea một bảng nhân viên là bảng cha, một bảng tổ chức bao gồm cấu trúc tổ chức và sau đó một bảng nhiệm vụ có cấu trúc người được chỉ định và phân cấp (người chuyển đến). Trong đó có FK cho cả hai. – HLGEM

13

Tôi giả định Departments.EmployeeID của bạn là một trưởng phòng ban. Những gì tôi muốn làm là làm cho cột đó có thể vô hiệu; sau đó bạn có thể tạo ra bộ phận đầu tiên, sau đó là nhân viên.

+1

Không có lý do gì bạn không thể có khóa ngoài trên trường không có giá trị. – Bill

+0

Không, bạn không thể. Nhưng bạn vẫn có thể đặt chỉ mục trên đó để giúp gia nhập ... –

+0

Hỗn loạn: Chắc chắn đó là một tùy chọn. Hóa đơn: Ý tưởng là mỗi Bộ phải có một trưởng phòng. – Tom

1

Bạn có thể tạo một hàng trong bảng Vụ 'Unassigned'

Để tạo một bộ phận mới với một nhân viên mới, bạn sau đó sẽ

  1. Tạo Employee (EmployeeA) trong 'Unassigned' Bộ
  2. Tạo bộ phận mới (DepartmentA) với nhân viên EmployeeA
  3. cập nhật EmployeeA được trong DepartmentA

Điều này sẽ không làm mất hiệu lực lược đồ hiện tại của bạn và bạn có thể thiết lập một nhiệm vụ để chạy thường xuyên để kiểm tra không có thành viên nào của bộ phận chưa được chỉ định.

Bạn cũng sẽ cần phải tạo một nhân viên mặc định là nhân viên của Unassigned

EDIT:

Giải pháp bởi sự hỗn loạn được đề xuất là đơn giản hơn nhiều mặc dù

3

Vấn đề này có thể được giải quyết với các ràng buộc deferable .Các ràng buộc như vậy được kiểm tra khi toàn bộ giao dịch được cam kết, do đó cho phép bạn chèn cả nhân viên và bộ phận trong cùng một giao dịch, đề cập đến nhau. (Giả sử mô hình dữ liệu có ý nghĩa)

+0

Âm thanh giống như cách tiếp cận được mô tả bởi Spencer7593. Bất kỳ ai biết làm thế nào để điều đó trong MSSQL? – Tom

1

Có một vài thiết kế hay mà tôi đã sử dụng. Tất cả đều liên quan đến việc xóa "Employee" EmployeeID khỏi bảng Department và loại bỏ DepartmentID khỏi bảng Employee. Tôi đã nhìn thấy một vài câu trả lời đề cập đến nó, nhưng tôi sẽ làm rõ cách chúng tôi sử dụng nó:

Tôi thường kết thúc với một bảng liên kết mối quan hệ EmployeeDepartment - rất nhiều, thường với các cờ như IsManager, IsPrimaryManager, IsAdmin, IsBackupManager vv, làm rõ mối quan hệ Một số có thể bị ràng buộc để chỉ có một Trình quản lý Chính được phép cho mỗi bộ phận (mặc dù một người có thể là một PrimaryManager của nhiều phòng ban). Nếu bạn không thích bảng duy nhất, thì bạn có thể có nhiều bảng: EmployeeDepartment, ManagerDepartment, v.v. nhưng sau đó bạn có thể có các tình huống mà một người là người quản lý chứ không phải nhân viên, v.v.

Chúng tôi cũng thường được phép mọi người trở thành thành viên của nhiều phòng ban.

Để truy cập đơn giản, bạn có thể cung cấp chế độ xem thực hiện việc tham gia phù hợp.

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