Bir üst satır silinemez veya güncellenemez: yabancı anahtar kısıtlaması başarısız


170

Yaparken:

DELETE FROM `jobs` WHERE `job_id` =1 LIMIT 1 

Hatalar:

#1451 - Cannot delete or update a parent row: a foreign key constraint fails 
(paymesomething.advertisers, CONSTRAINT advertisers_ibfk_1 FOREIGN KEY 
(advertiser_id) REFERENCES jobs (advertiser_id))

İşte tablolarım:

CREATE TABLE IF NOT EXISTS `advertisers` (
  `advertiser_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `password` char(32) NOT NULL,
  `email` varchar(128) NOT NULL,
  `address` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `fax` varchar(255) NOT NULL,
  `session_token` char(30) NOT NULL,
  PRIMARY KEY (`advertiser_id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


INSERT INTO `advertisers` (`advertiser_id`, `name`, `password`, `email`, `address`, `phone`, `fax`, `session_token`) VALUES
(1, 'TEST COMPANY', '', '', '', '', '', '');

CREATE TABLE IF NOT EXISTS `jobs` (
  `job_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `advertiser_id` int(11) unsigned NOT NULL,
  `name` varchar(255) NOT NULL,
  `shortdesc` varchar(255) NOT NULL,
  `longdesc` text NOT NULL,
  `address` varchar(255) NOT NULL,
  `time_added` int(11) NOT NULL,
  `active` tinyint(1) NOT NULL,
  `moderated` tinyint(1) NOT NULL,
  PRIMARY KEY (`job_id`),
  KEY `advertiser_id` (`advertiser_id`,`active`,`moderated`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


INSERT INTO `jobs` (`job_id`, `advertiser_id`, `name`, `shortdesc`, `longdesc`, `address`, `active`, `moderated`) VALUES
(1, 1, 'TEST', 'TESTTEST', 'TESTTESTES', '', 0, 0);

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`);

Yanıtlar:


108

Olduğu gibi, başvurduğu işler tablosundaki satırı silmeden önce satırı reklamverenler tablosundan silmeniz gerekir. Bu:

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) 
      REFERENCES `jobs` (`advertiser_id`);

... aslında olması gerekenin tam tersidir. Olduğu gibi, reklamverenlerden önce işler tablosunda bir kayda sahip olmanız gerektiği anlamına gelir. Bu yüzden kullanmanız gerekir:

ALTER TABLE `jobs`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) 
      REFERENCES `advertisers` (`advertiser_id`);

Yabancı anahtar ilişkisini düzelttikten sonra, silme ifadeniz çalışır.


3
İlk satırda: "referans veren" yerine "referans veren" olması gerektiğini düşünmüyor musunuz? Yoksa terminolojinin referanslarının nasıl çalışması gerektiğini yanlış anladım mı?
Abraham Philip

6
@AbrahamPhilip Ben de aynı şeyi düşünüyordum. reklamverenler iş referansları.
keyser

270

Bunun basit yolu yabancı anahtar denetimini devre dışı bırakmak olabilir; değişiklikleri yapın ve ardından yabancı anahtar kontrolünü yeniden etkinleştirin.

SET FOREIGN_KEY_CHECKS=0; -- to disable them
SET FOREIGN_KEY_CHECKS=1; -- to re-enable them

171
Bu, sorunun çözümü değil, istenmeyecek kirli bir çözümdür.
madfriend

20
Benim durumumda: Sadece büyük bir SQL dosyası çalıştırdım ve son ifadelerden biri başarısız oldu, bu yüzden sadece tüm tabloları silmek, sözdizimi hatasını düzeltmek ve tekrar aradığımı yapmak istiyorum.
ekerner

1
Bunu yapacak olsaydın, neden sadece tüm kısıtlamaları kaldırmıyorsun?
Sablefoste

1
Gibi bir şey yaparken yararlıdır:REPLACE INTO tab_with_constraint ...
Maciek Łoziński

5
Bu cevabı iptal etmenin tek nedeni, kodunuzun size bağırmayı bırakmasını ve yazdığınız kodu anlamadan spagetti'ye daha da derinleşmesini istiyorsanız. İlk etapta yabancı anahtarlara sahip olmanın nedeni referans bütünlüğünü uygulamaktır. Kodunuzun kapatılması için bunları devre dışı bırakmanız gerekirse, büyük olasılıkla yabancı anahtarlarınızı devre dışı bırakmak yerine yeniden düşünmek istersiniz.
cytinus

38

Mevcut (muhtemelen kusurlu) tasarımınızın altında, başvurduğu işler tablosundaki satırı silmeden önce satırı reklamverenler tablosundan silmeniz gerekir.

Alternatif olarak, yabancı anahtarınızı üst tablodaki silme alt tablolardaki satırların otomatik olarak silinmesine neden olacak şekilde ayarlayabilirsiniz. Buna basamaklı silme denir. Şuna benziyor:

ALTER TABLE `advertisers`
ADD CONSTRAINT `advertisers_ibfk_1`
FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`)
ON DELETE CASCADE;

Diğerlerinin de işaret ettiği gibi, yabancı anahtarınızın, reklamverenler tablosunun gerçekten birincil anahtarı içerdiği ve iş tablosunun yabancı anahtarı içerdiğinden, bunun tersine gitmesi gerektiğini hissettiğini söyledikten sonra. Ben böyle yeniden yazmak:

ALTER TABLE `jobs`
ADD FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`advertiser_id`);

Ve basamaklı silme gerekli olmayacaktır.


18

Bir tabloyu bırakmak istiyorsanız, tek bir adımda aşağıdaki sorguyu çalıştırmalısınız

SET FOREIGN_KEY_CHECKS = 0; DROP TABLE tablo_adı;


13

@Alino Manzi tarafından belirtilen çözümü denedim ama wpdb kullanarak WordPress ile ilgili tablolarda benim için çalışmadı.

sonra kodu aşağıdaki gibi değiştirdim ve çalıştı

SET FOREIGN_KEY_CHECKS=OFF; //disabling foreign key

//run the queries which are giving foreign key errors

SET FOREIGN_KEY_CHECKS=ON; // enabling foreign key

6

Yabancı anahtarın geriye dönük olduğunu düşünüyorum. Deneyin:

ALTER TABLE 'jobs'
ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`advertiser_id`)

5

Aynı reklamveren_kimli birden fazla iş varsa, yabancı anahtarınız:

ALTER TABLE `jobs`
ADD CONSTRAINT `advertisers_ibfk_1` 
FOREIGN KEY (`advertiser_id`) 
REFERENCES `advertisers` (`advertiser_id`);

Aksi takdirde (durumunuzda başka bir yol varsa), işteki satır silinirse reklamverendeki satırların otomatik olarak silinmesini istiyorsanız, yabancı anahtarınızın sonuna 'SİLİNDİR SİL' seçeneğini ekleyin:

ALTER TABLE `advertisers`
ADD CONSTRAINT `advertisers_ibfk_1` 
FOREIGN KEY (`advertiser_id`) 
REFERENCES `jobs` (`advertiser_id`)
ON DELETE CASCADE;

Yabancı Anahtar kısıtlamalarına göz atın



2

Veritabanı oluşturduğunuzda veya tablo oluşturduğunuzda

Bu satırı en üstteki komut dosyasına veritabanı veya tablo oluştur

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;

Şimdi kayıtları tablodan silmek istiyor musunuz? o zaman şöyle yaz

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;
DELETE FROM `jobs` WHERE `job_id` =1 LIMIT 1

İyi şanslar!


2

Kullanmakta olduğum bu alternatif hakkında: yabancı anahtarın NULL olmasına izin verin ve sonra SET NULL'U SİL'i seçin .

Şahsen gereksiz komplikasyonları önlemek için " ON UPDATE CASCADE " i ve " ON DELETE SET NULL " u kullanmayı tercih ederim , ancak kurulumunuzda farklı bir yaklaşım isteyebilirsiniz. Ayrıca, NULL'ing yabancı anahtar değerleri, orada tam olarak ne olduğunu bilmediğiniz için komplikasyonlara yol açabilir. Bu nedenle, bu değişiklik uygulama kodunuzun çalışma biçimiyle yakından ilişkili olmalıdır.

Bu yardımcı olur umarım.


2

Ben bu sorunu vardı laravel göç de
aşağı düşüş tabloları sırası () metodu fark eder

Schema::dropIfExists('groups');
Schema::dropIfExists('contact');

işe yaramayabilir, ancak siparişi değiştirirseniz çalışır.

Schema::dropIfExists('contact');
Schema::dropIfExists('groups');

1

istemciyi en kısa zamanda desteklemeniz gerekiyorsa ve

FOREIGN_KEY_CHECKS

böylece veri bütünlüğü devre dışı bırakılabilir:

1) Yabancı Anahtarı Silin

ALTER TABLE `advertisers` 
DROP FOREIGN KEY `advertisers_ibfk_1`;

2) silme işleminizi sql veya api aracılığıyla etkinleştirin

3) yabancı anahtarı şemaya geri ekleyin

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`);

ancak, bu bir düzeltme, bu nedenle kendi sorumluluğunuzdadır, çünkü böyle bir yaklaşımın ana kusuru, daha sonra veri bütünlüğünü manuel olarak tutmaktır.


0

İşi silmeden önce başvurulan satırları silmek için bir tetikleyici oluşturabilirsiniz.

    DELIMITER $$
    CREATE TRIGGER before_jobs_delete 
        BEFORE DELETE ON jobs
        FOR EACH ROW 
    BEGIN
        delete from advertisers where advertiser_id=OLD.advertiser_id;
    END$$
    DELIMITER ;

0

Bu erorr ile ilgili ana sorun, hangi hatanın FK hatasını içerdiğiniError Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails bilmemesidir , bu nedenle çatışmayı çözmek zordur.

MySQL veya benzeri bir yöntem kullanıyorsanız , veritabanınız için bir ER diyagramı oluşturabileceğinizi öğrendim , o zaman hatayı tetikleyen çakışmaları gözden geçirebilir ve güvenle kaldırabilirsiniz.

  1. MySQL çalışma tezgahını kullanma
  2. Veritabanına tıklayın -> Tersine Mühendislik
  3. Doğru seçin connection
  4. Sonuna kadar, seçmeyi unutmayın databaseve tablesincelenmesi gerekir
  5. Şimdi ER diyagramınız var, hangi tablonun FK çakışması olduğunu görebilirsiniz

0

Temel olarak, bu tür hataların ardında yatan neden, sonunda birincil anahtarı (kök tablo) olan bir tupple'ı silmeye çalışmanızdır ve bu birincil anahtar alt tabloda yabancı anahtar olarak kullanılır. Bu senaryoda, üst tablo verilerini silmek için alt tablo verilerini (yabancı anahtarın kullanıldığı) kaldırmanız gerekir. Teşekkürler


0

Bu da bana oldu ve diğer tablolardan bir bağımlılık ve referans nedeniyle, girişi kaldıramadı. Ne yaptım tabloya bir silme sütunu (boolean türünde) eklenir. Bu alandaki değer, öğenin silinmek üzere işaretlenip işaretlenmediğini gösterir. Silinmek üzere işaretlenmişse, getirmeyin / kullanmayın; aksi takdirde kullanın.


-1

Belki CASCADE'İ SİL


34
Sorunu anlamadan körü körüne basamaklı bir silme eklemek (verileri yok eder), kişinin yapabileceği en kötü şeydir.
Tom H
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.