Làm cách nào để sử dụng xóa tầng với SQL Server?


332

Tôi có 2 bảng: T1 và T2, chúng là các bảng hiện có dữ liệu. Chúng tôi có mối quan hệ một đến nhiều giữa T1 và T2. Làm cách nào để thay đổi định nghĩa bảng để thực hiện xóa tầng trong SQL Server khi bản ghi từ T1 bị xóa, tất cả các bản ghi liên quan trong T2 cũng bị xóa.

Các ràng buộc nước ngoài là ở giữa chúng. Tôi không muốn bỏ các bảng hoặc tạo một trình kích hoạt để xóa dữ liệu cho T2. Ví dụ, khi tôi xóa một nhân viên, tất cả các hồ sơ đánh giá cũng sẽ biến mất.

T1 - Nhân viên,

Employee ID      
Name
Status

T2 - Đánh giá hiệu suất,

Employee ID - 2009 Review
Employee ID - 2010 Review

Câu trả lời:


362

Bạn sẽ cần đến,

  • Bỏ các ràng buộc khóa ngoại hiện có,
  • Thêm một cái mới với ON DELETE CASCADEcài đặt được kích hoạt.

Cái gì đó như:

ALTER TABLE dbo.T2
   DROP CONSTRAINT FK_T1_T2   -- or whatever it's called

ALTER TABLE dbo.T2
   ADD CONSTRAINT FK_T1_T2_Cascade
   FOREIGN KEY (EmployeeID) REFERENCES dbo.T1(EmployeeID) ON DELETE CASCADE

3
Đội của tôi và tôi vừa làm điều này. Chúng tôi đã phải DROP các ràng buộc của chúng tôi và thêm chúng. Điều này làm việc cho chúng tôi.
Daniel L. VanDenBosch

2
Làm thế nào là điều này có lợi cho việc xóa cứng? Một xóa mềm sẽ không bao giờ có một vấn đề ràng buộc. Có vẻ hoàn toàn ngược lại với tôi.
Maxx

2
@Maxx Trong xóa cứng, bạn xóa một bản ghi và không cần lo lắng về các thanh ghi mồ côi, trong khi xóa mềm bạn cần thực hiện thủ công.
Ronaldo Araújo Alves

318

Để thêm "Xóa tầng" vào khóa ngoại hiện có trong SQL Server Management Studio:

Đầu tiên, chọn Khóa ngoại của bạn và mở "DROP và Tạo để .." trong cửa sổ Truy vấn mới.

nhập mô tả hình ảnh ở đây

Sau đó, chỉ cần thêm ON DELETE CASCADEvào ADD CONSTRAINTlệnh:

n Và nhấn nút "Thực thi" để chạy truy vấn này.

Nhân tiện, để có được danh sách Khóa ngoại của bạn và xem cái nào đã bật "Xóa tầng", bạn có thể chạy tập lệnh này:

SELECT 
   OBJECT_NAME(f.parent_object_id) AS 'Table name',
   COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Field name',
   delete_referential_action_desc AS 'On Delete'
FROM sys.foreign_keys AS f,
     sys.foreign_key_columns AS fc,
     sys.tables t 
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
ORDER BY 1

Và nếu bạn thấy rằng bạn không thể có DROPmột bảng cụ thể do ràng buộc Khóa ngoài, nhưng bạn không thể tìm ra FK nào gây ra sự cố, thì bạn có thể chạy lệnh này:

sp_help 'TableName'

SQL trong bài viết đó liệt kê tất cả các FK tham chiếu một bảng cụ thể.

Hy vọng tất cả điều này sẽ giúp.

Lời xin lỗi cho ngón tay dài. Tôi chỉ cố gắng để làm cho một điểm.


163

Bạn có thể làm điều này với SQL Server Management Studio.

→ Nhấp chuột phải vào thiết kế bảng và đi đến Mối quan hệ và chọn khóa ngoại ở khung bên trái và trong ngăn bên phải, mở rộng menu "Đặc tả CHỌN và CẬP NHẬT" và chọn "Xếp tầng" làm Quy tắc xóa.

Studio quản lý máy chủ SQL


xin chào, sự khác biệt giữa 4 là gì, không bật tầng cho phép dễ dàng xóa tất cả dữ liệu trong một bảng. Làm cách nào tôi có thể xem tất cả các khóa phụ thuộc / fk trên bảng này, không phải từ bảng này. Ngay cả sau khi xóa tất cả FK, tôi vẫn gặp lỗi
aggie

@aggie - Bạn có thể kiểm tra các phụ thuộc bằng cách - Nhấp chuột phải vào bảng -> "Xem phụ thuộc" Ngoài ra, máy chủ sql sẽ cung cấp cho bạn lỗi chi tiết với tên bảng và tên cột như thế này "Câu lệnh XÓA bị xung đột với ràng buộc TÀI LIỆU THAM KHẢO" FK_Child1_Parent1 ". Xung đột xảy ra trong cơ sở dữ liệu "TESTDB", bảng "dbo.Child1", cột 'Parent1ID'. "
Palanikumar

@aggie - Ngoài ra trường hợp thứ 4 "Đặt mặc định" là, Bạn phải đặt ràng buộc mặc định trong cột Khóa ngoài, khi chúng tôi xóa cha mẹ thì giá trị mặc định sẽ được thay thế trong các bảng con. (Lưu ý: Giá trị mặc định phải khớp với bảng cha.) Để biết thêm thông tin, hãy truy cập mssqltips.com/sqlservertip/2365/ chủ đề
Palanikumar

Điều này rất hữu ích. Tôi tự hỏi, tại sao không có Quy tắc chèn? Nói cách khác, khi tôi thêm một hàng vào T1, tôi muốn mục nhập tương ứng trong T2 được tạo tự động.
Robert M.

@RobertM. Bởi vì điều đó không có ý nghĩa. Làm thế nào nó biết những giá trị nào để CHỨNG MINH? Bạn có thể sử dụng các kích hoạt INSERT để tạo các hàng con, hãy thử nghiên cứu điều đó.
Dan Bechard

46

Sử dụng một cái gì đó như

ALTER TABLE T2
ADD CONSTRAINT fk_employee
FOREIGN KEY (employeeID)
REFERENCES T1 (employeeID)
ON DELETE CASCADE;

Điền vào tên cột chính xác và bạn sẽ được đặt. Như mark_s đã nêu chính xác, nếu bạn đã có một ràng buộc khóa ngoài, bạn có thể cần phải xóa cái cũ trước rồi tạo cái mới.


41
@marc_s - thực tế, bạn có thể thêm khóa ngoại thứ hai vào chính xác các cột giống nhau ở cả hai bên và nó sẽ hoạt động chính xác. Nếu làm việc trong môi trường sản xuất không có thời gian chết, có thể nên giới thiệu FK mới với tầng, sau đó thả FK cũ hơn, thay vì để một cửa sổ trên bàn khi không có FK. (Chỉ được thử nghiệm trên SQL 2008)
Damien_The_Unbeliever

Chính xác. Tôi đã thử điều này, và nó hoạt động. Không cần phải bỏ các ràng buộc khóa ngoại đầu tiên. Cảm ơn vi đa trả lơi.
Bíchvan Nguyễn

15

Đầu tiên để kích hoạt thuộc tính ONCascade:

1.Drop các ràng buộc khóa ngoại hiện có

2. thêm một cái mới với cài đặt ON DELETE CASCADE được bật

Ví dụ:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 

ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

Thứ hai để vô hiệu hóa thuộc tính ONCascade:

1.Drop các ràng buộc khóa ngoại hiện có

2.Thêm một cái mới với cài đặt BẬT XÓA KHÔNG CÓ HÀNH ĐỘNG

Ví dụ:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE NO ACTION 
END

15

ON DELETE CASCADE
Nó chỉ định rằng dữ liệu con sẽ bị xóa khi dữ liệu gốc bị xóa.

CREATE TABLE products
( product_id INT PRIMARY KEY,
  product_name VARCHAR(50) NOT NULL,
  category VARCHAR(25)
);

CREATE TABLE inventory
( inventory_id INT PRIMARY KEY,
  product_id INT NOT NULL,
  quantity INT,
  min_level INT,
  max_level INT,
  CONSTRAINT fk_inv_product_id
    FOREIGN KEY (product_id)
    REFERENCES products (product_id)
    ON DELETE CASCADE
);

Đối với khóa ngoại này, chúng tôi đã chỉ định ON DELETE CASCADEmệnh đề yêu cầu SQL Server xóa các bản ghi tương ứng trong bảng con khi dữ liệu trong bảng cha bị xóa. Vì vậy, trong ví dụ này, nếu giá trị sản phẩm bị xóa khỏi bảng sản phẩm, các bản ghi tương ứng trong bảng kiểm kê sử dụng sản phẩm này cũng sẽ bị xóa.


-2

Nếu mối quan hệ một đến nhiều là từ T1 đến T2 thì nó không đại diện cho một chức năng và do đó không thể được sử dụng để suy ra hoặc suy ra một hàm nghịch đảo đảm bảo giá trị T2 kết quả không bỏ qua các tuple của T1 tham gia T2 có giá trị khấu trừ , bởi vì không có hàm nghịch đảo hợp lệ. (đại diện cho các chức năng là mục đích của các khóa chính.) Câu trả lời trong SQL nghĩ là có, bạn có thể làm điều đó. Câu trả lời trong suy nghĩ quan hệ là không bạn không thể làm điều đó. Xem những điểm không rõ ràng trong Codd 1970. Mối quan hệ sẽ phải có nhiều điểm từ một đến T1.


-10

Tôi nghĩ bạn không thể xóa thuộc tính bảng nếu đây là dữ liệu sản xuất thực tế, chỉ cần xóa các nội dung không ảnh hưởng đến lược đồ bảng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.