Yabancı anahtar kısıtlamalı tablo nasıl kesilir?


648

Neden değil KESILMESINDEN üzerinde mygroupçalışması? Ben sahip olmama rağmen ON DELETE CASCADE SET:

HATA 1701 (42000): Yabancı anahtar kısıtlaması ( mytest. instance, CONSTRAINT instance_ibfk_1FOREIGN KEY ( GroupID) REFERANSLAR mytest. mygroup( ID))

drop database mytest;
create database mytest;
use mytest;

CREATE TABLE mygroup (
   ID    INT NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=InnoDB;

CREATE TABLE instance (
   ID           INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
   GroupID      INT NOT NULL,
   DateTime     DATETIME DEFAULT NULL,

   FOREIGN KEY  (GroupID) REFERENCES mygroup(ID) ON DELETE CASCADE,
   UNIQUE(GroupID)
) ENGINE=InnoDB;

Yanıtlar:


1001

TRUNCATEÜzerine FK kısıtlamaları uygulanmış bir tabloyu kullanamazsınız ( TRUNCATEile aynı değildir DELETE).

Bu sorunu gidermek için aşağıdaki çözümlerden birini kullanın. Her ikisi de veri bütünlüğüne zarar verme riski taşır.

Seçenek 1:

  1. Kısıtlamaları kaldır
  2. yapmak TRUNCATE
  3. Artık hiçbir yere referansı olmayan satırları manuel olarak silin
  4. Kısıtlamalar oluşturun

2. Seçenek: önerdiği user447951 içinde verdikleri yanıta

SET FOREIGN_KEY_CHECKS = 0; 
TRUNCATE table $table_name; 
SET FOREIGN_KEY_CHECKS = 1;

46
@barjonah: aslında veri bütünlüğünü bozabilir (bkz. stackoverflow.com/questions/5452760/… ). Dolayısıyla, gerçek dünyada "ışık" olarak adlandırdığınız şeyin kötü bir uygulama olduğu düşünülür. PS: downvote için teşekkürler
zerkms

1
Artık yetim yabancı anahtarları bulmanın çok iyi bir yolu (veri bütünlüğünü geri
yükle

truncate önce yabancı anahtar devre dışı da iyi bir yoldur, ben kaynak başarıyla yaptı: stackoverflow.com/questions/8641703/…
Dung

2
@ Yabancı anahtar kontrollerinin devre dışı bırakılmasına yalnızca geliştirme döneminde izin verilir. Mevcut ilişkileri bozar. zerkms, veri bütünlüğü konusunda% 100 haklıdır. Tamamen boşaltmayı (veya en azından ilgili tüm tabloları) planlamadığınız sürece, çalışan bir veritabanındaki yabancı anahtar denetimlerini devre dışı
bırakamazsınız

1
@Kamlesh benim çözümüm değil, bunu barbarca bir şekilde yapmamayı tavsiye ettim.
zerkms

1308

Evet yapabilirsin:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;

Bu ifadelerle, tablolarınıza FOREIGN KEYkısıtlamalara uymayan satırlar girme riskiniz vardır .


30
SET FOREIGN_KEY_CHECKS = 1 ayarlamalıyız; sonra tekrar?
vinc3m1

77
Hayır. Bu ayar yalnızca bağlantı sırasında geçerlidir. Bağlantı kesilir kesilmez, bir sonraki bağlantı 1'e geri döner.
The Pellmeister

7
Bu, başvurulan tablodaki 'ON DELETE' olayını uygulamaz, bu nedenle bu tam bir yanıt değildir.
Ömer Sabiç

5
PHPMYADMIN içinde kullanıyorsanız, bu yalnızca aynı SQL penceresinde (a ile ayrılmış ;) tüm işlemleri kullanırsanız çalışır . Bunun nedeni, her yeni web SQL çağrısının 1 değerini sıfırlayacağıdır FOREIGN_KEY_CHECKS.
Sablefoste

1
İlgilendiğiniz takdirde artık yabancı anahtarları (veri bütünlüğünü geri yükleme) bulmanın çok iyi bir yolu http://stackoverflow.com/a/12085689/997776
SandorRacz

173

Ben sadece:

DELETE FROM mytest.instance;
ALTER TABLE mytest.instance AUTO_INCREMENT = 1;

5
Akıllı. Yine de tüm kayıtları silmek istediğinizde, otomatik artışı da sıfırlayabilirsiniz.
winkbrace

6
Açıkçası bunu yapmanın en iyi yolu budur. Kısıtlamaları kaybetme riski yok, sadece sil. Daha DELETEyavaş performans sergilediğini fark etmekte fayda var TRUNCATE. Ancak bu eylem genellikle nadiren gerçekleştirildiğinden, bu önemli değildir.
phil294

Bu, yapmak istediğiniz tek şeyse iyidir, ancak DELETEçok fazla satırınız varsa kesinlikle acımasız olabilir - çünkü günlüklere çarpar, TRUNCATEsadece verileri çıkarır. Gerçekten kullanım durumuna bağlıdır.
Jeff

1
delete deyimini kullandığımda 1175 hatasını bildiriyor: Güvenli güncelleme modunu kullanıyorsunuz, sadece SET SQL_SAFE_UPDATES = 0 ekleyin; o zaman sorun değil
tyan

Bu çözümü kullanırken, mükemmel hale getirmek için error 1175: You are using safe update mode,...değişiklik silme maddesini bildirir DELETE FROM mydb.mytable where id != 0.
Shihe Zhang

17

yapabilirsin

DELETE FROM `mytable` WHERE `id` > 0

1
Ben bur denedim, aşağıdaki hata ortaya çıktı: Hata Kodu: 1142. DELETE komutu 'mytable' tablosu için 'root' @ 'localhost' kullanıcısına reddedildi
AAEM

ya da sadece SİLmytable
Miloslav Milo Janoušek

Bu otomatik artışı artırmaz.
vivek_23

13

Gereğince MySQL belgeler , KESILMESINDEN yabancı anahtar ilişkileri olan tablolara kullanılamaz. Tam bir alternatif AFAIK yoktur.

Kontraintin düşürülmesi ON DELETE ve ON UPDATE'i çağırmaz. ATM'nin düşünebileceği tek çözüm şunlardan biri:

  • tüm satırları sil, yabancı anahtarları bırak, kes, anahtarları yeniden oluştur
  • tüm satırları sil, auto_increment'i sıfırla (kullanılıyorsa)

MySQL'de TRUNCATE henüz tam bir özellik değil gibi görünüyor (ayrıca tetikleyicileri çağırmaz). Yoruma bakın


7
MySQL'in TRUNCATEeksik olmasıyla ilgili bir not - kesme, tetikleyicileri vb. Çağırması gerekmez. Olsaydı, sadece aynı olurdu DELETE! Satır bağımsızdır, bu nedenle satırla ilgili işlemler gerçekleştiremez (tetikleyicileri çağırmak veya yabancı anahtarları incelemek gibi). Oracle ve Sql Server'da da aynı şekilde çalışır .
Simon MᶜKenzie

8

PhpMyAdmin kullanıyorsanız kolay.

Sekme Enable foreign key checksaltındaki seçeneğin işaretini kaldırın SQLve çalıştırınTRUNCATE <TABLE_NAME>

resim açıklamasını buraya girin


8

Bu soru sorulmuş olsa da, ben bilmiyordum, ama şimdi phpMyAdmin kullanıyorsanız, sadece veritabanını açıp kısaltmak istediğiniz tabloları seçebilirsiniz.

  • Altta birçok seçenek içeren bir açılır menü var. Açın ve Emptybaşlığın altındaki seçeneği seçin Delete data or table.
  • Otomatik olarak bir sonraki sayfaya yönlendirilir ve burada onay kutusunda çağrılan bir seçenek vardır Enable foreign key checks. Sadece seçimini kaldırın ve düğmesine basın; Yesseçilen tablo (lar) kısaltılacaktır.

Belki dahili olarak user447951'in cevabında önerilen sorguyu çalıştırır , ancak phpMyAdmin arayüzünden kullanmak çok uygundur.


7

MYSQL Veritabanında test edildi

Çözüm 1:

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;

Çözüm 2:

DELETE FROM table1;
ALTER TABLE table1 AUTO_INCREMENT = 1;
TRUNCATE table1;

Bu benim için çalışıyor. Umarım bu da size yardımcı olacaktır. Bu soruyu sorduğun için teşekkürler.


6

Cevap aslında Seçenek 1'de belirtildiği gibi zerkms tarafından verilen cevaptır :

Seçenek 1 : Veri bütünlüğüne zarar vermeyen:

  1. Kısıtlamaları kaldır
  2. TRUNCATE yap
  3. Artık hiçbir yere referansı olmayan satırları manuel olarak silin
  4. Kısıtlamalar oluşturun

Zor kısmı Kısıtlamaları Kaldırma , bu yüzden birisinin bunu nasıl yapacağını bilmesi gerekiyorsa, nasıl olduğunu söylemek istiyorum:

  1. FOREIGN KEY adının (aşağıdaki resimde kırmızı çerçeve) SHOW CREATE TABLE <Table Name>ne olduğunu görmek için sorguyu çalıştırın :

    resim açıklamasını buraya girin

  2. Koş ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign Key Name>. Bu, yabancı anahtar kısıtlamasını kaldıracaktır.

  3. İlişkili Dizini bırakın (tablo yapısı sayfası aracılığıyla) ve işiniz bitti.

yabancı anahtarları yeniden oluşturmak için:

ALTER TABLE <Table Name>
ADD FOREIGN KEY (<Field Name>) REFERENCES <Foreign Table Name>(<Field Name>);

3

Sadece CASCADE kullanın

TRUNCATE "products" RESTART IDENTITY CASCADE;

Ancak basamaklı silmelere hazır olun)


3
OP, MySQL olarak etiketlendi. Bu Postgres için geçerli olsa da, MySQL'de yanlıştır.
Peter

1

Tablolar için veritabanı motoru farklıysa, bu hatayı alırsınız, bu nedenle bunları InnoDB olarak değiştirin

ALTER TABLE my_table ENGINE = InnoDB;

0

Eski yabancı anahtar kontrol durumunu ve sql modunu almak, modeli veritabanıyla senkronize ederken tabloyu Mysql Workbench'in yaptığı gibi kesmenin / Bırakmanın en iyi yoludur.

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;`
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

DROP TABLE TABLE_NAME;
TRUNCATE TABLE_NAME;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
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.