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: -?)

Álvaro González
sumber
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.

MarkR
sumber
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 ...

Karlis Rode
sumber
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
Flakron Bytyqi
sumber
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;
JackD
sumber
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;

M_ Fa
sumber
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;")
yeyo
sumber
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`;
Vadim Pluzhinsky
sumber
0

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

Abdulrahman K
sumber
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. :)

Aadil Masavir
sumber
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