Ràng buộc khóa ngoại Bogus không thành công


110

Tôi nhận được thông báo lỗi này:

LỖI 1217 (23000) ở dòng 40: Không thể xóa hoặc cập nhật hàng mẹ: ràng buộc khóa ngoại không thành công

... khi tôi cố gắng làm rơi một cái bàn:

DROP TABLE IF EXISTS `area`;

... được định nghĩa như thế này:

CREATE TABLE `area` (
  `area_id` char(3) COLLATE utf8_spanish_ci NOT NULL,
  `nombre_area` varchar(30) COLLATE utf8_spanish_ci NOT NULL,
  `descripcion_area` varchar(100) COLLATE utf8_spanish_ci NOT NULL,
  PRIMARY KEY (`area_id`),
  UNIQUE KEY `nombre_area_UNIQUE` (`nombre_area`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

Điều buồn cười là tôi đã bỏ tất cả các bảng khác trong lược đồ có khóa ngoại chống lại area. Trên thực tế, cơ sở dữ liệu trống ngoại trừ areabảng.

Làm thế nào nó có thể có các hàng con nếu không có bất kỳ đối tượng nào khác trong cơ sở dữ liệu? Theo như tôi biết, InnoDB không cho phép khóa ngoại trên các lược đồ khác, phải không?

(Tôi thậm chí có thể chạy một RENAME TABLE area TO something_elselệnh: -?)


Có thể bảng là một phần của mối quan hệ Tham chiếu-Toàn vẹn trong một lược đồ khác không?
Raj More

Tôi có một số bản sao khác của ứng dụng nên luôn có thể. Tuy nhiên, về cơ bản CONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id), cú pháp tôi sử dụng là không có tên lược đồ trên tham chiếu bảng: -?
Álvaro González

Câu trả lời:


101

Hai khả năng:

  1. Có một bảng trong một lược đồ khác ("cơ sở dữ liệu" trong thuật ngữ mysql) có tham chiếu FK
  2. Từ điển dữ liệu nội bộ innodb không đồng bộ với từ điển mysql.

Bạn có thể xem đó là bảng nào (dù sao cũng là một trong số chúng) bằng cách thực hiện "HIỂN THỊ TÌNH TRẠNG KỸ THUẬT INNODB" sau khi thả không thành công.

Nếu nó trở thành trường hợp thứ hai, tôi sẽ kết xuất và khôi phục toàn bộ máy chủ nếu bạn có thể.

MySQL 5.1 trở lên sẽ cung cấp cho bạn tên của bảng có FK trong thông báo lỗi.


1
Tôi không còn có thể tái tạo vấn đề. Từ điển không đồng bộ nổi bật như một lý do có thể. Tôi sẽ kiểm tra nó trong ngày và xem những SHOW ENGINE INNODB STATUSbáo cáo.
Álvaro González

3
Cảm ơn bạn vì câu trả lời này! Tôi có một bảng nhiều đến nhiều vẫn tham chiếu đến bảng mà chúng tôi không thể bỏ, vì vậy tôi phải bỏ bảng đó trước.
Christian Oudard

5
SHOW ENGINE INNODB STATUS liệt kê lỗi khóa ngoại cuối cùng trong "LỖI PHÍM NGOÀI MỚI NHẤT". Điều này có một dấu thời gian.
bbrame

có thể có một bảng vẫn có khóa tham chiếu đến bảng chủ đề. nó là trong trường hợp của tôi, như thế này.
RT

Tiết kiệm rất nhiều thời gian. Đã đánh rơi db dưới "LỖI PHÍM NGOẠI TỆ MỚI NHẤT"
Sand1512

121

Theo yêu cầu, bây giờ như một câu trả lời ...

Khi sử dụng Trình duyệt truy vấn MySQL hoặc phpMyAdmin, có vẻ như một kết nối mới được mở cho mỗi truy vấn ( bug.mysql.com/bug.php?id=8280 ), khiến việc viết tất cả các câu lệnh drop trong một truy vấn là điều cần thiết.

SET FOREIGN_KEY_CHECKS=0; 
DROP TABLE my_first_table_to_drop; 
DROP TABLE my_second_table_to_drop; 
SET FOREIGN_KEY_CHECKS=1; 

Nơi SET FOREIGN_KEY_CHECKS=1phục vụ như một biện pháp an ninh bổ sung ...


2
Đối với những người tạo kết xuất bằng phpMyAdmin, có một tùy chọn "Tắt kiểm tra khóa ngoại" sẽ tự động thêm SET FOREIGN_KEY_CHECKS=0;vào đầu kết xuất.
Mike

Có vẻ như phpMyAdmin đã triển khai tính năng đáng yêu này, bây giờ tôi đang chờ mysqlWorkbench làm điều tương tự! :)
Karlis Rode

@CodeMed FYI, tôi chấp nhận câu trả lời của MarkR vì nó đưa ra lời giải thích hợp lý cho vấn đề — mặc dù tôi thừa nhận rằng tôi không thể xác minh điều đó vì tôi đã không đối mặt với vấn đề tương tự này trong 6 năm sau đó, thậm chí chưa một lần. Câu trả lời này và các câu trả lời trước đó cung cấp một cách giải quyết (rất tốt cho điều đó) nhưng không thực sự giải quyết được chính câu hỏi và vì bạn chỉ có thể chấp nhận một câu trả lời mà tôi đã phải chọn.
Álvaro González

1
Cảnh báo: đây không phải là giải pháp mà chỉ là cách giải quyết của kẻ lười biếng. Sau khi sử dụng tính năng này (với các bản ghi trên một số bảng khác trỏ đến bảng đã bị loại bỏ), bạn sẽ gặp phải các khóa ngoại treo lơ lửng làm phá vỡ tính nhất quán ( C trong ACID ) của cơ sở dữ liệu của bạn và các ứng dụng của bạn sẽ bắt đầu ném các ngoại lệ vào khắp nơi. Mày đã được cảnh báo.
bekce

Mặc dù tôi chắc chắn rằng cảnh báo của bekce nên được hiểu và chú ý, giải pháp này đã hiệu quả với tôi, trong tình huống mà tôi tự tin rằng tôi cũng đang loại bỏ tất cả các bảng đang trỏ đến các bảng có ràng buộc khóa ngoại rắc rối.
user1147171

47

Tắt kiểm tra khóa ngoài

SET FOREIGN_KEY_CHECKS=0

62
Lệnh đúng có vẻ là SET FOREIGN_KEY_CHECKS=0và nó sửa được thông báo lỗi. Bạn có bất kỳ ý tưởng nào về lý do tại sao điều này được yêu cầu? Các khóa ngoại có được lưu vào bộ nhớ đệm ngay cả khi các bảng đã biến mất không?
Álvaro González

1
Nói thật, tôi không biết tại sao vấn đề như vậy lại phát sinh, nhưng hãy đảm bảo rằng bạn tắt tính năng kiểm tra khóa mỗi khi bạn thực hiện một số thay đổi hoặc cập nhật lớn. Nó đã xảy ra với tôi vài lần, khiến tôi mất ngủ nhiều ngày.
Flakron Bytyqi

55
Hãy đảm bảo SET FOREIGN_KEY_CHECKS=1;sau khi bạn hoàn thành!
pedro_sland

5
Khi sử dụng Trình duyệt truy vấn MySQL hoặc phpMyAdmin, có vẻ như một kết nối mới được mở cho mỗi truy vấn ( bug.mysql.com/bug.php?id=8280 ), khiến việc viết tất cả các câu lệnh drop trong một truy vấn là điều cần thiết. SET FOREIGN_KEY_CHECKS=0; DROP TABLE my_first_table_to_drop; DROP TABLE my_second_table_to_drop; SET FOREIGN_KEY_CHECKS=1; Trường hợp FOREIGN_KEY_CHECKS SET = 1 đóng vai trò như một biện pháp bảo mật thêm ...
Kārlis Rode

1
@KarlisRode, Bravo cho nhận xét về phpMyAdmin. Nếu bạn đặt nó như một câu trả lời, tôi sẽ +1 nó.
Sablefoste

28

từ blog này :

Bạn có thể tạm thời vô hiệu hóa kiểm tra khóa ngoại:

SET FOREIGN_KEY_CHECKS=0;

Chỉ cần đảm bảo khôi phục chúng sau khi bạn hoàn thành việc làm rối tung:

SET FOREIGN_KEY_CHECKS=1;

Câu trả lời hay vì tôi đang phát triển trên local :)
Adelin

Đó là một cách giải quyết hợp lệ (tôi có thể xác nhận nó hoạt động) nhưng mục blog được liên kết không thực sự nói về tình huống trong câu hỏi này (một cơ sở dữ liệu đã trống lưu cho một bảng).
Álvaro González

6

hy vọng nó làm việc

SET Foreign_key_checks = 0; DROP BẢNG table name; SET Foreign_key_checks = 1;


Vâng, nó hoạt động, như nhiều lần nó được đề cập trước đây ;-)
Álvaro González

1

Trên Rails, người ta có thể làm như sau bằng cách sử dụng rails console:

connection = ActiveRecord::Base.connection
connection.execute("SET FOREIGN_KEY_CHECKS=0;")

0

Có thể bạn đã gặp lỗi khi làm việc với bảng này trước đây. Bạn có thể đổi tên bảng và thử xóa lại.

ALTER TABLE `area` RENAME TO `area2`;
DROP TABLE IF EXISTS `area2`;

0

tôi đã tìm thấy một giải pháp dễ dàng, xuất cơ sở dữ liệu, chỉnh sửa nó những gì bạn muốn chỉnh sửa trong trình soạn thảo văn bản, sau đó nhập nó. Làm xong


4
Đó là một giải pháp thú vị, điều đó có lẽ không thực sự xảy ra. Thay vào đó, bất kỳ điều gì cần thay đổi đều phải được thực hiện thông qua DBMS. Chỉnh sửa kết xuất cơ sở dữ liệu trong trình soạn thảo văn bản có vẻ giống như một con đường chín muồi cho các vấn đề.
Brandon Anzaldi

1
Tôi không thực sự hiểu bạn thích gì. Kết xuất cơ sở dữ liệu, xóa CREATE TABLEmã và tải lại kết xuất ... sẽ không làm cho MySQL loại bỏ bảng. Và nếu bạn có nghĩa là khôi phục kết xuất trong một cơ sở dữ liệu mới ... Nếu bạn muốn xóa tất cả các bảng giống như tôi, một cơ sở dữ liệu mới được tạo sẽ trống. Nếu bạn muốn giữ một số bảng, SET FOREIGN_KEY_CHECKS=0giải pháp được đề cập ở mọi nơi ở đây hoạt động tốt và đơn giản hơn; và bạn có thể không cần chỉnh sửa kết xuất vì bản sao dữ liệu mới của bạn có thể sẽ không có từ điển dữ liệu không đồng bộ.
Álvaro González

-1

Không thể xóa hoặc cập nhật hàng mẹ: ràng buộc khóa ngoại không thành công ( table1. user_role, CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60NGOẠI KHÓA ( user_id) TÀI LIỆU THAM KHẢO user( id))

Những gì tôi đã làm trong hai bước đơn giản. đầu tiên tôi xóa hàng con trong bảng con như

mysql> xóa khỏi table2 nơi role_id = 2 && user_id = 20;

Truy vấn OK, 1 hàng bị ảnh hưởng (0,10 giây)

và bước thứ hai là xóa cha mẹ

xóa khỏi table1 trong đó id = 20;

Truy vấn OK, 1 hàng bị ảnh hưởng (0,12 giây)

Bằng cách này, tôi giải quyết vấn đề có nghĩa là Xóa con sau đó Xóa cha mẹ

tôi hy vọng bạn hiểu nó. :)


Vui lòng đọc lại câu hỏi. Bạn không thể xóa một bảng không tồn tại.
Álvaro González

trong trường hợp này, chúng ta có thể loại bỏ ràng buộc khóa ngoại sau đó cố gắng xóa bảng. chúng ta có thể Thả khóa ngoại như sau ALTER TABLE này <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
Aadil Masavir
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.