2009-12-07 33 views
25

Tôi có một hàng trong một bảng. Hàng này có một cột ID được tham chiếu trong một vài bảng khác với hàng triệu hàng. Câu lệnh SQL để xóa hàng luôn luôn hết thời gian. Từ thiết kế của tôi, tôi biết hàng tôi muốn xóa không bao giờ được tham chiếu ở bất kỳ nơi nào khác. Do đó tôi muốn SQL bỏ qua việc phải kiểm tra tất cả các bảng khác cho một tham chiếu khóa ngoài tới hàng này và xóa hàng ngay lập tức. Có cách nào nhanh chóng để làm điều này trong SQL 2008? Có lẽ điều gì đó dọc theo các dòng:Xóa một hàng SQL bỏ qua tất cả các khóa và ràng buộc nước ngoài

DELETE FROM myTable where myTable.ID = 6850 IGNORE CONSTRAINTS 

Hoặc điều gì đó dọc theo các dòng đó.

+3

Bạn đã cân nhắc thêm chỉ mục vào các cột tham chiếu chính trên các bảng có liên quan chưa? Nếu chưa có, điều này sẽ cho phép SQL nhanh chóng xác định xem có bất kỳ hàng nào khác tham chiếu đến hàng bạn đang cố xóa hay không và cũng có thể cung cấp cho bạn hiệu suất đáng kể ... –

+0

Tôi có thể đề xuất một cách tiếp cận khác. Trong hệ thống của tôi, hầu hết (hàng trăm) bảng trỏ đến một dbo.Company.Id. Ngay cả khi xóa một công ty trống, không có tham chiếu, chỉ làm cho DB kiểm tra tính toàn vẹn của FK trong hàng tỷ hàng. Giải pháp: Chỉ cần sử dụng xóa hợp lý. – jean

Trả lời

30

Bạn có thể đặt các ràng buộc trên bảng/cột đó để không kiểm tra tạm thời, sau đó bật lại các ràng buộc. dạng tổng quát sẽ là:

ALTER TABLE TableName NOCHECK CONSTRAINT ConstraintName 

Sau đó bật lại tất cả các ràng với

ALTER TABLE TableName CHECK CONSTRAINT ConstraintName 

tôi cho rằng điều này sẽ chỉ là tạm thời mặc dù? Bạn rõ ràng sẽ không muốn làm điều này một cách nhất quán.

1

Trên tất cả các bảng với các phím nước ngoài trỏ đến thế này, sử dụng:

ALTER TABLE MyOtherTable NOCHECK CONSTRAINT fk_name 
17

Vâng, chỉ cần chạy

DELETE FROM myTable where myTable.ID = 6850 

VÀ ĐỘNG LET LET XÁC NHẬN THE CONS ĐÀO TẠO.

Nếu bạn đang cố gắng trở nên 'thông minh' và vô hiệu hóa ràng buộc, bạn sẽ phải trả một mức giá rất lớn: cho phép trở lại các ràng buộc phải xác minh mỗi hàng thay vì chỉ xóa. Có những cờ bên trong SQL giữ cho biết rằng một ràng buộc là 'đáng tin cậy' hay không. Bạn 'tối ưu hóa' sẽ dẫn đến việc thay đổi các cờ này thành 'false' (nghĩa là SQL không còn tin tưởng các ràng buộc) hoặc nó phải xác minh lại chúng từ đầu.

Xem Guidelines for Disabling Indexes and ConstraintsNon-trusted constraints and performance.

Trừ khi bạn thực hiện một số phép đo rắn chứng minh rằng việc xác minh ràng buộc của thao tác DELETE là một nút cổ chai hiệu suất, hãy để động cơ thực hiện công việc của mình.

+1

Chỉ để có một số số thực: xóa 10 triệu bản ghi ra khỏi bảng 12M thực sự chậm hơn 2 phút với 1 ràng buộc tạm thời bị hủy kích hoạt so với kích hoạt (12:18 so với 10:28) - SQL-Server – Remco

+1

Trong một số trường hợp, Giống như việc tạo một bảng tên miền trên DB tạo lại, nó là bắt buộc và OK để vô hiệu hóa kiểm tra FK, bởi vì nếu bạn tìm thấy ai đó bằng cách nào đó đã thêm mục tra cứu với giá trị mã không chính xác, bạn phải xóa mục đó và tạo lại nó với cả mã đúng và giá trị văn bản. – ProfK

7

Không trong bất kỳ trường hợp nào đều vô hiệu hóa các ràng buộc. Đây là một thực hành cực kỳ ngu ngốc. Bạn không thể duy trì tính toàn vẹn dữ liệu nếu bạn làm những việc như thế này. Toàn vẹn dữ liệu là việc xem xét đầu tiên của một cơ sở dữ liệu bởi vì không có nó, bạn không có gì cả.

Phương pháp đúng là xóa khỏi bảng con trước khi cố gắng xóa bản ghi gốc. Có thể bạn đã hết thời gian vì bạn đã thiết lập các tầng deltes, đây là một thực tiễn không tốt trong một cơ sở dữ liệu lớn.

+6

Nó có thể rất hữu ích trong các tình huống nhất định khi bạn thực sự biết những gì bạn đang làm và đảm bảo rằng tất cả các ràng buộc được thỏa mãn vào cuối giao dịch. Ví dụ, SqlBulkCopy bỏ qua các ràng buộc theo mặc định, điều này có ý nghĩa khi bạn nghĩ về nó. – chris

+1

@chris, cụm từ chính có thực sự biết những gì bạn đang làm. Toàn bộ những người này không hỏi làm thế nào để vô hiệu hóa các ràng buộc trên internet. – HLGEM

1

Tôi muốn xóa tất cả các bản ghi khỏi cả hai bảng vì đó là tất cả dữ liệu thử nghiệm. Tôi đã sử dụng SSMS GUI để tạm thời vô hiệu hóa ràng buộc FK, sau đó tôi chạy truy vấn DELETE trên cả hai bảng và cuối cùng tôi đã bật lại ràng buộc FK.

Để vô hiệu hóa chế FK:

  1. mở rộng đối tượng cơ sở dữ liệu [1]
  2. mở rộng đối tượng bảng phụ thuộc [2]
  3. mở rộng thư mục 'Keys
  4. nhấp chuột phải vào khóa ngoài
  5. chọn tùy chọn 'Sửa đổi'
  6. thay đổi tùy chọn 'Thực thi ràng buộc khóa ngoại' thành 'Không'
  7. đóng cửa sổ 'Ngoại chính mối quan hệ'
  8. đóng thiết kế bảng tab
  9. khi xác nhận nhắc nhở lưu các thay đổi
  10. chạy cần thiết xóa các truy vấn
  11. kích hoạt lại ràng buộc khoá ngoại giống như cách bạn chỉ vô hiệu hóa nó.

[1] trong 'Object Explorer' cửa sổ, có thể được truy cập thông qua 'View' tùy chọn trình đơn, hoặc F8

[2] nếu bạn không chắc chắn mà bảng là một trong những phụ thuộc , bạn có thể kiểm tra bằng cách nhấp chuột phải vào bảng được đề cập và chọn tùy chọn 'Xem phụ thuộc'.

+0

Tôi thấy dễ dàng hơn khi chỉ xóa các bảng trong đối tượng thám hiểm và để cho Batch tạo lại chúng (chạy lại lần nữa cho các bảng không thể xóa do các ràng buộc FK.). – appl3r

1

Tôi biết đây là một chuỗi cũ, nhưng tôi đã hạ cánh tại đây khi các lần xóa hàng của tôi bị chặn bởi các ràng buộc khóa ngoại. Trong trường hợp của tôi, thiết kế bảng của tôi cho phép các giá trị "NULL" trong cột bị ràng buộc. Trong các hàng sẽ bị xóa, tôi đã thay đổi giá trị cột bị ràng buộc thành "NULL" (không vi phạm Ràng buộc khóa ngoại) và sau đó xóa tất cả các hàng.

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