Batasan kunci asing palsu gagal


110

Saya mendapatkan pesan kesalahan ini:

ERROR 1217 (23000) di baris 40: Tidak dapat menghapus atau memperbarui baris induk: batasan kunci asing gagal

... ketika saya mencoba menjatuhkan tabel:

DROP TABLE IF EXISTS `area`;

... didefinisikan seperti ini:

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;

Lucunya, saya sudah menjatuhkan semua tabel lain dalam skema yang memiliki kunci asing area. Sebenarnya database kosong kecuali areatabel.

Bagaimana mungkin memiliki baris anak jika tidak ada objek lain dalam database? Sejauh yang saya tahu, InnoDB tidak mengizinkan kunci asing di skema lain, bukan?

(Saya bahkan dapat menjalankan RENAME TABLE area TO something_elseperintah: -?)


Apakah mungkin tabel tersebut merupakan bagian dari hubungan Referensial-Integritas di skema lain?
Raj More

Saya memiliki beberapa salinan lain dari aplikasi sehingga selalu memungkinkan. Namun, sintaks yang saya gunakan pada dasarnya adalah CONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id), tidak ada nama skema pada referensi tabel: -?
Álvaro González

Jawaban:


101

Dua kemungkinan:

  1. Ada tabel dalam skema lain ("database" dalam terminologi mysql) yang memiliki referensi FK
  2. Kamus data internal innodb tidak sinkron dengan yang mysql.

Anda dapat melihat tabel mana itu (salah satunya, bagaimanapun) dengan melakukan "SHOW ENGINE INNODB STATUS" setelah penurunan gagal.

Jika ternyata kasus terakhir, saya akan membuang dan memulihkan seluruh server jika Anda bisa.

MySQL 5.1 dan di atasnya akan memberi Anda nama tabel dengan FK di pesan kesalahan.


1
Saya tidak lagi dapat mereproduksi masalah tersebut. Kamus yang tidak sinkron menonjol sebagai alasan yang mungkin. Saya akan mengujinya hari ini dan melihat SHOW ENGINE INNODB STATUSlaporan apa .
Álvaro González

3
Terima kasih atas jawaban ini! Saya memiliki tabel banyak-ke-banyak yang masih mereferensikan tabel yang tidak dapat kami jatuhkan, jadi saya harus menjatuhkan tabel itu terlebih dahulu.
Christian Oudard

5
SHOW ENGINE INNODB STATUS mencantumkan kesalahan kunci asing terakhir di bawah "ERROR KUNCI ASING TERBARU". Ini memiliki stempel waktu.
bbrame

mungkin ada tabel yang masih memiliki kunci referensi ke tabel subjek. itu dalam kasus saya, seperti ini.
RT

Menghemat banyak waktu. Menjatuhkan db di bawah "LATEST FOREIGN KEY ERROR"
Sand1512

121

Sesuai permintaan, sekarang sebagai jawaban ...

Saat menggunakan MySQL Query Browser atau phpMyAdmin, tampaknya koneksi baru dibuka untuk setiap kueri ( bugs.mysql.com/bug.php?id=8280 ), sehingga perlu untuk menulis semua pernyataan drop dalam satu kueri, misalnya.

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

Dimana SET FOREIGN_KEY_CHECKS=1berfungsi sebagai tindakan pengamanan ekstra ...


2
Bagi mereka yang membuat dump menggunakan phpMyAdmin, ada opsi "Nonaktifkan pemeriksaan kunci asing" yang secara otomatis akan ditambahkan SET FOREIGN_KEY_CHECKS=0;ke awal dump.
Mike

Sepertinya phpMyAdmin telah mengimplementasikan fitur yang bagus ini, sekarang saya menunggu mysqlWorkbench melakukan hal yang sama! :)
Karlis Rode

@CodeMed FYI, saya menerima jawaban MarkR karena memberikan penjelasan untuk masalah yang masuk akal — meskipun saya akui saya tidak dapat memverifikasinya karena saya belum pernah menghadapi masalah yang sama dalam 6 tahun berikutnya, tidak sekali pun. Jawaban ini dan sebelumnya memberikan solusi (bagus untuk kebaikan itu) tetapi tidak benar-benar menjawab pertanyaan itu sendiri dan karena Anda hanya dapat menerima satu jawaban yang harus saya pilih.
Álvaro González

1
Peringatan: ini bukan solusi tetapi hanya solusi bagi orang malas. Setelah menggunakan ini (dengan catatan pada beberapa tabel lain yang menunjuk ke tabel yang dijatuhkan), Anda akan mengalami kunci asing yang menggantung yang secara fatal merusak konsistensi ( C dalam ACID ) database Anda dan aplikasi Anda akan mulai membuang pengecualian di semua tempat. Anda telah diperingatkan.
bekce

Meskipun saya yakin peringatan bekce harus dipahami dan diperhatikan, solusi ini berhasil untuk saya, dalam situasi di mana saya yakin bahwa saya juga menjatuhkan semua tabel yang mengarah ke tabel dengan batasan kunci asing yang merepotkan.
pengguna1147171

47

Nonaktifkan pemeriksaan kunci asing

SET FOREIGN_KEY_CHECKS=0

62
Perintah yang benar tampaknya SET FOREIGN_KEY_CHECKS=0dan itu memperbaiki pesan kesalahan. Apakah Anda tahu mengapa ini diperlukan? Apakah kunci asing disimpan dalam cache bahkan setelah tabel hilang?
Álvaro González

1
Sejujurnya, saya tidak tahu mengapa masalah seperti itu muncul, tetapi pastikan Anda menonaktifkan pemeriksaan kunci setiap kali Anda membuat beberapa perubahan atau pembaruan besar. Itu telah terjadi pada saya beberapa kali, membuat saya tidak tidur selama berhari-hari.
Flakron Bytyqi

55
Pastikan SET FOREIGN_KEY_CHECKS=1;setelah Anda selesai!
pedro_sland

5
Saat menggunakan MySQL Query Browser atau phpMyAdmin, tampaknya koneksi baru dibuka untuk setiap kueri ( bugs.mysql.com/bug.php?id=8280 ), sehingga perlu untuk menulis semua pernyataan drop dalam satu kueri, misalnya. SET FOREIGN_KEY_CHECKS=0; DROP TABLE my_first_table_to_drop; DROP TABLE my_second_table_to_drop; SET FOREIGN_KEY_CHECKS=1; Dimana SET FOREIGN_KEY_CHECKS = 1 berfungsi sebagai tindakan keamanan ekstra ...
Karlis Rode

1
@KarlisR, Bravo atas komentarnya di phpMyAdmin. Jika Anda ingin menjawabnya, saya akan memberi +1.
Sablefoste

28

dari blog ini :

Anda dapat menonaktifkan pemeriksaan kunci asing untuk sementara:

SET FOREIGN_KEY_CHECKS=0;

Pastikan untuk memulihkannya setelah Anda selesai mengotak-atik:

SET FOREIGN_KEY_CHECKS=1;

Jawaban yang bagus karena saya mengembangkan di lokal :)
Adelin

Ini adalah solusi yang valid (saya dapat mengonfirmasi bahwa itu berfungsi) tetapi entri blog yang ditautkan tidak benar-benar berbicara tentang skenario dalam pertanyaan ini (database yang sudah kosong, simpan untuk satu tabel).
Álvaro González

6

semoga berhasil

ATUR cek_kunci_ asing = 0; DROP TABLE table name; ATUR cek_kunci_ asing = 1;


Ya, itu berhasil, karena beberapa kali telah disebutkan sebelumnya ;-)
Álvaro González

1

Di Rails, seseorang dapat melakukan hal berikut dengan menggunakan rails console:

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

0

Mungkin Anda pernah menerima kesalahan saat bekerja dengan tabel ini sebelumnya. Anda dapat mengganti nama tabel dan mencoba menghapusnya lagi.

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

0

saya menemukan solusi yang mudah, ekspor database, edit apa yang ingin Anda edit di editor teks, lalu impor. Selesai


4
Itu solusi yang menarik, yang mungkin seharusnya tidak terjadi. Sebaliknya, apa pun yang perlu diubah harus dilakukan melalui DBMS. Mengedit dump database di editor teks sepertinya merupakan jalan yang tepat untuk mengatasi masalah.
Brandon Anzaldi

1
Saya tidak begitu mengerti apa yang Anda sukai. Membuang database, menghapus CREATE TABLEkode dan memuat dump lagi ... tidak akan membuat MySQL menghapus tabel. Dan jika Anda bermaksud memulihkan dump dalam database baru ... Jika Anda ingin menghapus semua tabel seperti saya, database yang baru dibuat akan kosong. Jika Anda ingin menyimpan beberapa tabel, SET FOREIGN_KEY_CHECKS=0solusi yang disebutkan di mana-mana di sini berfungsi dengan baik dan lebih sederhana; dan Anda mungkin tidak perlu mengedit dump karena salinan baru data Anda mungkin tidak memiliki kamus data yang tidak sinkron.
Álvaro González

-1

Tidak dapat menghapus atau memperbarui baris induk: batasan kunci asing gagal ( table1. user_role, CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60FOREIGN KEY ( user_id) REFERENCES user( id))

Apa yang saya lakukan dalam dua langkah sederhana. pertama saya menghapus baris anak di tabel anak seperti

mysql> hapus dari tabel2 di mana role_id = 2 && user_id = 20;

Kueri OK, 1 baris terpengaruh (0,10 dtk)

dan langkah kedua sebagai menghapus induk

hapus dari table1 dimana id = 20;

Kueri OK, 1 baris terpengaruh (0,12 dtk)

Dengan ini saya memecahkan Masalah yang berarti Hapus Anak lalu Hapus orang tua

Saya harap Anda mendapatkannya. :)


Silakan baca pertanyaannya lagi. Anda tidak dapat menghapus tabel yang tidak ada.
Álvaro González

dalam skenario ini kita dapat menghapus batasan kunci asing kemudian mencoba untuk menghapus tabel. kita dapat melepaskan kunci asing seperti ini ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
Aadil Masavir
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.