Kesalahan Mysql 1452 - Tidak dapat menambah atau memperbarui baris anak: batasan kunci asing gagal

237

Saya mengalami sedikit masalah aneh. Saya mencoba menambahkan kunci asing ke satu tabel yang mereferensikan yang lain, tetapi gagal karena beberapa alasan. Dengan pengetahuan MySQL saya yang terbatas, satu-satunya hal yang mungkin dapat dicurigai adalah bahwa ada kunci asing pada tabel berbeda yang merujuk pada referensi yang saya coba referensi.

Saya sudah melakukan SHOW CREATE TABLEquery pada kedua tabel, sourcecodes_tagsadalah tabel dengan kunci asing, sourcecodesadalah tabel yang direferensikan.

CREATE TABLE `sourcecodes` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `user_id` int(11) unsigned NOT NULL,
 `language_id` int(11) unsigned NOT NULL,
 `category_id` int(11) unsigned NOT NULL,
 `title` varchar(40) CHARACTER SET utf8 NOT NULL,
 `description` text CHARACTER SET utf8 NOT NULL,
 `views` int(11) unsigned NOT NULL,
 `downloads` int(11) unsigned NOT NULL,
 `time_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`),
 KEY `user_id` (`user_id`),
 KEY `language_id` (`language_id`),
 KEY `category_id` (`category_id`),
 CONSTRAINT `sourcecodes_ibfk_3` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `sourcecodes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `sourcecodes_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

CREATE TABLE `sourcecodes_tags` (
 `sourcecode_id` int(11) unsigned NOT NULL,
 `tag_id` int(11) unsigned NOT NULL,
 KEY `sourcecode_id` (`sourcecode_id`),
 KEY `tag_id` (`tag_id`),
 CONSTRAINT `sourcecodes_tags_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Ini adalah kode yang menghasilkan kesalahan:

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE
Zim
sumber
2
Bisakah Anda juga memposting perintah insert / update Anda yang menghasilkan kesalahan?
Zed
64
Apakah meja Anda kosong ketika Anda menambahkan kunci asing ini?
Zed
12
coba jalankan kueri ini untuk melihat apakah ada sourcecode_id yang bukan merupakan id asli: SELECT sourcecode_id DARI sourcecode_tags MANA sourcecode_id TIDAK DI (SELECT id FROM sourcecodes AS tmp);
Zed
11
Terima kasih Zed, itu adalah masalah salah satu tabel memiliki data di dalamnya. Memikirkannya sekarang masuk akal bahwa itu gagal karena ada hal-hal yang merujuk barang-barang yang tidak ada, tetapi saya tidak akan pernah bisa menebaknya. Terima kasih!
Zim
2
Mengapa gagal jika tabel kosong?
theblackpearl

Jawaban:

226

Kemungkinan besar sourcecodes_tagstabel Anda mengandung sourcecode_idnilai yang tidak lagi ada di sourcecodestabel Anda . Anda harus menyingkirkan itu dulu.

Berikut ini kueri yang dapat menemukan ID itu:

SELECT DISTINCT sourcecode_id FROM 
   sourcecodes_tags tags LEFT JOIN sourcecodes sc ON tags.sourcecode_id=sc.id 
WHERE sc.id IS NULL;
tidak
sumber
UPDATE sourcecodes_tags SET sourcecode_id = NULL WHERE sourcecode_id NOT IN (SELECT id FROM sourcecodes)harus membantu untuk menyingkirkan ID tersebut. Atau jika nulltidak diizinkan sourcecode_id, maka hapus baris itu atau tambahkan nilai-nilai yang hilang ke sourcecodestabel.
naXa
Saya berpikir sama tetapi, bagi saya SELECT Tchild.id FROM Tchild INNER JOIN Tmain ON Tmain.id = Tchild.fk_id WHERE Tmain.id IS NULLtidak mengembalikan apa-apa, jadi masalahnya ada di tempat lain !?
Meloman
Ahh ini masalahnya bagiku. Saya mencoba untuk lari UPDATE `homestead`.`automations` SET `deleted_at`=NULL WHERE deleted_at IS NOT NULL;, yang tidak melibatkan kunci asing sama sekali, jadi saya bingung. Tetapi kenyataan bahwa tabel kontak saya tidak memiliki beberapa catatan yang dirujuk oleh tabel otomasi menyebabkannya membuang "Kode Kesalahan: 1452. Tidak dapat menambah atau memperbarui baris anak: batasan kunci asing gagal".
Ryan
99

Saya memiliki masalah yang sama dengan database MySQL saya tetapi akhirnya, saya mendapat solusi yang berhasil untuk saya.
Karena di meja saya semuanya baik-baik saja dari sudut pandang mysql (kedua tabel harus menggunakan mesin InnoDB dan tipe data dari setiap kolom harus dari jenis yang sama yang mengambil bagian dalam batasan kunci asing).
Satu-satunya hal yang saya lakukan adalah menonaktifkan pemeriksaan kunci asing dan kemudian mengaktifkannya setelah melakukan operasi kunci asing.
Langkah-langkah yang saya ambil:

SET foreign_key_checks = 0;
alter table tblUsedDestination add constraint f_operatorId foreign key(iOperatorId) references tblOperators (iOperatorId); Query
OK, 8 rows affected (0.23 sec) Records: 8  Duplicates: 0  Warnings: 0
SET foreign_key_checks = 1;
Prakash
sumber
49
foreign_key_checks ada karena suatu alasan. Jika Anda tidak dapat menambahkan kunci asing karena melanggar batasan, Anda harus memperbaiki data terlebih dahulu. Mematikan cek lalu menambahkan kunci membuat Anda dalam kondisi tidak konsisten. Pemeriksaan kunci asing menambah overhead, jika Anda tidak ingin menggunakannya, maka gunakan myisam sebagai gantinya.
cs_alumnus
5
@AbuSadatMohammedYasin tidak seharusnya tidak: pertanyaan bertanya "apa yang terjadi" dan jawaban ini tidak berusaha menjelaskannya. Seperti yang disebutkan cs_alumnus, ada masalah yang lebih besar: semua nilai baru yang seharusnya merujuk nilai lain di tabel lain (seperti yang harus dilakukan kunci Asing ) mungkin tidak menunjukkan apa-apa, menciptakan keadaan yang tidak konsisten. Penjelasan Cayetano yang singkat dan efektif memungkinkan Anda untuk menemukan nilai mana yang harus Anda perbarui sebelum membuat batasan sehingga Anda tidak akan terkejut dengan pertanyaan yang seharusnya mengembalikan nilai yang seharusnya ada!
Armfoot
55

Gunakan NOT INuntuk menemukan di mana kendala membatasi :

SELECT column FROM table WHERE column NOT IN 
(SELECT intended_foreign_key FROM another_table)

jadi, lebih khusus:

SELECT sourcecode_id FROM sourcecodes_tags WHERE sourcecode_id NOT IN 
(SELECT id FROM sourcecodes)

EDIT: INdan NOT INoperator diketahui jauh lebih cepat daripada JOINoperator, juga lebih mudah untuk membangun, dan ulangi.

Ryan Ward
sumber
1
Jadi, jika saya memahami ini dengan benar, kita dapat menambahkan kunci asing ke tabel yang sudah memiliki data di dalamnya, tetapi hanya jika baris anak ada untuk setiap baris di tabel induk? Jika tidak ada baris anak untuk setiap baris dalam tabel induk (yang merupakan apa yang Anda temukan), maka skrip kunci asing akan gagal.
Vincent
@Vincent jika menurut tabel induk Anda maksud tabel direferensikan, maka ya! Karenanya dengan Cayetano's pilih Anda mendapatkan semua baris yang Anda butuhkan untuk memperbarui / menghapus dari tabel "anak" Anda sebelum Anda menambahkan kendala baru (FK). Setelah semuanya menunjuk ke nilai di "another_table", maka Anda siap untuk mulai!
Armfoot
23

Pangkas tabel dan kemudian coba tambahkan Kendala FK .

Saya tahu solusi ini agak canggung tetapi berhasil 100%. Tetapi saya setuju bahwa ini bukan solusi ideal untuk mengatasi masalah, tetapi saya harap ini membantu.

Shankar Damodaran
sumber
4
Tidak perlu memotong semuanya. "UPDATE sourcecodes_tags SET sourcecode_id = NULL MANA sourcecode_id TIDAK DI (PILIH id DARI kode sumber)" harus cukup. Atau jika nol tidak diizinkan di "sourcecode_id", maka hapus baris itu atau tambahkan nilai-nilai yang hilang ke tabel "sourcecode".
Torben
1
Terkadang, jika data menambah PK kenaikan otomatis, itu memaksa Anda untuk memotong.
François Breton
2
@ShankarDamodaran tidak yakin mengapa memotong tabel berfungsi tetapi solusi ini bekerja dengan baik untuk saya. Saya bisa membuat hubungan saya berfungsi ... TERIMA KASIH!
MizAkita
@MizAkita berfungsi karena menghapus baris yang tidak memiliki nilai yang sesuai di tabel lain, memungkinkan batasan baru dibuat. Jika Anda baru saja menemukan baris-baris itu dan memperbarui atau menghapusnya (seperti saran Cayetano ), Anda tidak perlu menghapus baris-baris lainnya ...
Armfoot
@Armfoot - Saya punya masalah ini saat menambahkan baris pertama ke tabel dengan kunci asing. Jadi saya tidak punya baris untuk mencari.
Krewetka
16

Bagi saya, masalah ini sedikit berbeda dan sangat mudah untuk diperiksa dan dipecahkan.

Anda harus memastikan KEDUA tabel Anda adalah InnoDB. Jika salah satu tabel, yaitu tabel referensi adalah MyISAM, batasannya akan gagal.

    SHOW TABLE STATUS WHERE Name =  't1';

    ALTER TABLE t1 ENGINE=InnoDB;
zmonteca
sumber
14

Ini juga terjadi ketika menetapkan kunci asing ke parent.id ke child.column jika child.column sudah memiliki nilai 0 dan tidak ada nilai parent.id adalah 0

Anda perlu memastikan bahwa setiap child.column adalah NULL atau memiliki nilai yang ada di parent.id

Dan sekarang saya membaca pernyataan no aja, itulah yang dia validasi.

fyrye
sumber
14

Saya memiliki masalah yang sama hari ini. Saya menguji empat hal, beberapa di antaranya sudah disebutkan di sini:

  1. Apakah ada nilai di kolom anak Anda yang tidak ada di kolom induk (selain NULL, jika kolom anak nullable)

  2. Apakah kolom anak dan orang tua memiliki tipe data yang sama?

  3. Apakah ada indeks pada kolom induk yang Anda referensikan? MySQL sepertinya memerlukan ini untuk alasan kinerja ( http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html )

  4. Dan yang ini menyelesaikannya untuk saya: Apakah kedua tabel memiliki susunan yang identik?

Saya punya satu meja di UTF-8 dan yang lainnya di iso-sesuatu. Itu tidak berhasil. Setelah mengubah iso-table menjadi UTF-8 collation, kendala dapat ditambahkan tanpa masalah. Dalam kasus saya, phpMyAdmin bahkan tidak menampilkan tabel anak dalam iso-encoding di dropdown untuk membuat batasan kunci asing.

Michael Helwig
sumber
7

Tampaknya ada beberapa nilai tidak valid untuk baris kolom 0 yang bukan kunci asing yang valid sehingga MySQL tidak dapat menetapkan batasan kunci asing untuknya.

Anda dapat mengikuti langkah-langkah ini:

  1. Jatuhkan kolom yang telah Anda coba atur batasan FK.

  2. Tambahkan lagi dan tetapkan nilai defaultnya sebagai NULL.

  3. Coba atur batasan kunci asing lagi.

Milad Rahimi
sumber
5

Saya akan masalah yang sama, saya memeriksa baris tabel saya dan menemukan ada beberapa ketidakcocokan dengan nilai bidang yang saya ingin mendefinisikan kunci asing. Saya mengoreksi nilai itu, mencoba lagi dan masalahnya selesai.

Mostafa -T
sumber
4

Saya akhirnya menghapus semua data di tabel saya, dan menjalankan alter lagi. Berhasil. Bukan yang brilian, tetapi menghemat banyak waktu, terutama aplikasi Anda masih dalam tahap pengembangan tanpa data pelanggan.

VHanded
sumber
4

coba ini

SET foreign_key_checks = 0;

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE

SET foreign_key_checks = 1;
Carlo Guevarra
sumber
2

Saya memiliki masalah yang sama persis ini sekitar tiga kali berbeda. Dalam setiap contoh itu karena satu (atau lebih) catatan saya tidak sesuai dengan kunci asing baru. Anda mungkin ingin memperbarui catatan Anda yang ada untuk mengikuti batasan sintaks kunci asing sebelum mencoba menambahkan kunci itu sendiri. Contoh berikut umumnya mengisolasi catatan masalah:

SELECT * FROM (tablename)
    WHERE (candidate key) <> (proposed foreign key value) 
        AND (candidate key) <> (next proposed foreign key value)

ulangi AND (candidate key) <> (next proposed foreign key value)dalam kueri Anda untuk setiap nilai dalam kunci asing.

Jika Anda memiliki banyak catatan, ini bisa sulit, tetapi jika meja Anda cukup kecil, seharusnya tidak terlalu lama. Saya tidak super luar biasa dalam sintaks SQL, tetapi ini selalu mengisolasi masalah bagi saya.

mopsyd
sumber
2

Kosongkan data tabel Anda dan jalankan perintah. Itu akan berhasil.

vijayrana
sumber
VHanded memberikan jawaban yang sama 3 tahun yang lalu. Semoga saja tidak ada data penting di tabel ...
xlecoustillier
1

Saya sedang menyiapkan solusi ini dan contoh ini dapat membantu.

Basis data saya memiliki dua tabel (email dan kartu kredit) dengan kunci utama untuk ID mereka. Tabel lain (klien) merujuk ke tabel ID ini sebagai kunci asing. Saya punya alasan untuk memisahkan email dari data klien.

Pertama saya memasukkan data baris untuk tabel yang direferensikan (email, credit_card) kemudian Anda mendapatkan ID untuk masing-masing, ID tersebut diperlukan di tabel ketiga (klien).

Jika Anda tidak memasukkan terlebih dahulu baris dalam tabel yang direferensikan, MySQL tidak akan dapat membuat korespondensi ketika Anda memasukkan baris baru di tabel ketiga yang merujuk kunci asing.

Jika Anda pertama kali memasukkan baris yang direferensikan untuk tabel yang direferensikan, maka baris yang merujuk ke kunci asing, tidak ada kesalahan terjadi.

Semoga ini membantu.

SubstanceMX
sumber
mysql> masukkan ke nilai email (email) ('[email protected]'); mysql> masukkan ke nilai ndtc (ndtc, tahun, bulan) ('1111222233334444', '2000', '01'); mysql> masukkan ke klien (nombres, apellidos, telefono, idNDTC, idEmail) nilai ('myname', 'myapp', '5555555555', 1,1);
SubstanceMX
1

Pastikan nilainya ada di tabel lain jika tidak Anda akan mendapatkan kesalahan ini, di kolom yang sesuai ditugaskan.

Jadi jika kolom yang ditugaskan ditugaskan untuk id baris dari tabel lain, pastikan ada baris yang ada di tabel jika tidak kesalahan ini akan muncul.

Kingsley Mitchell
sumber
1

Anda dapat mencoba contoh ini

 START TRANSACTION;
 SET foreign_key_checks = 0;
 ALTER TABLE `job_definers` ADD CONSTRAINT `job_cities_foreign` FOREIGN KEY 
 (`job_cities`) REFERENCES `drop_down_lists`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
 SET foreign_key_checks = 1;
 COMMIT;

Catatan: jika Anda menggunakan phpmyadmin cukup hapus centang Aktifkan pemeriksaan kunci asing

sebagai contoh masukkan deskripsi gambar di sini

semoga soloution ini memperbaiki masalah Anda :)

Fouad Mekkey
sumber
1

Anda hanya perlu menjawab satu pertanyaan:

Apakah meja Anda sudah menyimpan data? (Terutama meja termasuk kunci asing.)

Jika jawabannya adalah ya, maka satu-satunya hal yang perlu Anda lakukan adalah menghapus semua catatan, maka Anda bebas menambahkan kunci asing apa pun ke tabel Anda.

Hapus instruksi: Dari anak (yang termasuk tabel kunci asing) ke tabel induk.

Alasan Anda tidak dapat menambahkan kunci asing setelah entri data karena inkonsistensi tabel, bagaimana Anda akan berurusan dengan kunci asing baru pada data yang sebelumnya diisi tabel?

Jika jawabannya tidak, maka ikuti instruksi lainnya.

tak seorangpun
sumber
0
UPDATE sourcecodes_tags
SET sourcecode_id = NULL
WHERE sourcecode_id NOT IN (
  SELECT id FROM sourcecodes);

harus membantu untuk menyingkirkan ID tersebut. Atau jika nulltidak diizinkan sourcecode_id, maka hapus baris itu atau tambahkan nilai-nilai yang hilang ke sourcecodestabel.

NaXa
sumber
0

Saya memiliki masalah yang sama dan menemukan solusi, NULLbukan menempatkan NOT NULLpada kolom kunci asing. Berikut ini kueri:

ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;

MySQL telah menjalankan kueri ini!

akelec
sumber
0

Dalam kasus saya, saya membuat tabel baru dengan struktur yang sama, membuat hubungan dengan tabel lain, lalu mengekstraksi data dalam CSV dari tabel lama yang memiliki masalah, kemudian mengimpor CSV ke tabel baru dan menonaktifkan pemeriksaan kunci asing dan menonaktifkan interupsi impor, semua data saya dimasukkan ke tabel baru yang tidak memiliki masalah berhasil, kemudian menghapus tabel lama.

Ini berhasil untuk saya.

Shamal Sabah
sumber