外部キー制約テーブルを切り捨てる方法は?


648

なぜないTRUNCATEmygroup仕事は?私が持っON DELETE CASCADE SETているのに:

エラー1701(42000):外部キー制約(mytestinstance、CONSTRAINT instance_ibfk_1FOREIGN KEY(GroupID)REFERENCES mytestmygroupID))で参照されているテーブルを切り捨てることはできません

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;

回答:


1001

あなたはできませんTRUNCATEそれに適用されるFK制約を持つテーブル(TRUNCATEと同じではありませんDELETE)。

これを回避するには、これらのソリューションのいずれかを使用します。どちらもデータの整合性を損なうリスクがあります。

オプション1:

  1. 制約を削除
  2. 演じる TRUNCATE
  3. どこにも参照されなくなった行を手動で削除する
  4. 制約を作成する

オプション2: ユーザー447951 が回答提案

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

46
@barjonah:実際には、データの整合性が損なわれる可能性があります(stackoverflow.com/questions/5452760/…を参照)。したがって、現実世界で「ライト」と呼ぶのは悪い習慣だと考えられています。PS:投票に感謝します
zerkms

1
これは、孤立した外部キ​​ーを見つけるための非常に良い方法です(データの整合性を復元)http://stackoverflow.com/a/12085689/997776
SandorRacz

:切り捨ての前に無効にする外部キーも良い方法ですが、私はソースからの成功でそれをやったstackoverflow.com/questions/8641703/...
ズン

2
@Dungによる外部キーチェックの無効化は、開発期間にのみ許可されています。既存の関係を壊します。zerkmsは、データの整合性に関して100%正しいです。完全に(または少なくともすべての関連テーブルを)空にする予定がない限り、作業中のデータベースで外部キーチェックを無効にすることはできません
NoobishPro

1
@Kamleshそれは私の解決策ではありません、私はそれを野蛮な方法でやらないようにアドバイスしました。
zerkms

1308

はい、できます:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;

これらのステートメントでは、FOREIGN KEY制約に準拠していない行をテーブルに入れるリスクがあります。


30
SET FOREIGN_KEY_CHECKS = 1を設定する必要がありますか?その後また?
vinc3m1

77
いいえ、必要ありません。設定は接続中のみ有効です。すぐに切断するよう、次の接続は、それが1に戻って設定されています
Pellmeister

7
これは、参照されるテーブルの「ON DELETE」イベントを適用しないため、完全な答えではありません。
Omer Sabic 2012年

5
PHPMYADMINで使用する場合、これは、すべてのトランザクションを同じSQLウィンドウ(で区切られている;)で使用する場合にのみ機能します。それぞれの新鮮なウェブSQLの呼び出しはリセットされますので、これはあるFOREIGN_KEY_CHECKS1に
Sablefoste

1
ここでは孤立した外部キーを見つけるための非常に良い方法は、あなたが興味を持っている場合には(データの整合性を復元する)であるhttp://stackoverflow.com/a/12085689/997776
SandorRacz

173

私は単にそれをやります:

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

5
スマート。とにかくすべてのレコードを削除したい場合は、自動増分をリセットすることもできます。
winkbrace

6
これは明らかにそれを行うための最良の方法です。制約を失うリスクはなく、単純に削除するだけです。のDELETEパフォーマンスが未満であることは注目に値しTRUNCATEます。ただし、このアクションは通常、ごくまれにしか実行されないため、これは問題になりません。
phil294 2015

これで十分な場合はこれで十分ですが、DELETE行数が多すぎる場合はログがヒットするTRUNCATEだけでデータが取り除かれるので、非常に残酷な場合があります。本当にユースケースに依存します。
ジェフ

1
deleteステートメントを使用すると、エラー1175が報告されます。セーフアップデートモードを使用しています。SETSQL_SAFE_UPDATES = 0を追加してください。その後、それは大丈夫です
tyan

このソリューションを使用すると、完全にerror 1175: You are using safe update mode,...変更するために変更削除句が報告されDELETE FROM mydb.mytable where id != 0ます。
Shihe Zhang

17

できるよ

DELETE FROM `mytable` WHERE `id` > 0

1
私は、それがBURしようとした次のエラーが登場します。エラーコード:1142 DELETEコマンドは、テーブルのために、ユーザー「ルート」@「localhost」のに拒否された「mytableは」
AAEM

または単にDELETE FROMmytable
ミロスラフMiloJanoušek19年

これは自動インクリメントをリセットしません。
vivek_23

13

mysqlのドキュメントに従って、TRUNCATEは外部キー関係のあるテーブルでは使用できません。完全な代替のAFAIKはありません。

制約を削除しても、ON DELETEとON UPDATEは呼び出されません。ATMで考えられる唯一の解決策は、次のいずれかです。

  • すべての行の削除、外部キーの削除、切り捨て、キーの再作成
  • すべての行を削除し、auto_incrementをリセットします(使用されている場合)

MySQLのTRUNCATEはまだ完全な機能ではないようです(トリガーを起動しません)。 コメントを見る


7
MySQL TRUNCATEが不完全であるという点についてのメモ-truncateはトリガーなどを呼び出すことは想定されていません。もしそうなら、それはDELETE!これは行に依存しないため、行に関連する操作(トリガーの呼び出しや外部キーの検査など)を実行できません。OracleSQL Serverで同じように機能します
SimonMᶜKenzie15年

8

phpMyAdminを使用している場合は簡単です。

タブのEnable foreign key checks下のオプションをオフにSQLして実行するだけですTRUNCATE <TABLE_NAME>

ここに画像の説明を入力してください


8

この質問は尋ねられましたが、私はそれについて知りませんでしたが、phpMyAdminを使用している場合は、データベースを開いて、切り捨てるテーブルを選択できます。

  • 下部には、多くのオプションがあるドロップダウンがあります。それを開きEmpty、見出しの下のオプションを選択しますDelete data or table
  • と呼ばれるチェックボックスにオプションがある自動的に次のページに移動しますEnable foreign key checks。選択を解除してYesボタンを押すだけで、選択したテーブルが切り捨てられます。

多分それは内部でuser447951の回答で提案されたクエリを実行しますが、phpMyAdminインターフェイスから使用するのは非常に便利です。


7

MYSQLデータベースでテスト済み

解決策1:

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;

解決策2:

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

これでうまくいきます。これもお役に立てば幸いです。この質問をしていただきありがとうございます。


6

オプション1で述べたように、答えは確かzerkmsによって提供されたものです

オプション1:データの整合性を損なうリスクがない場合:

  1. 制約を削除
  2. 切り捨てを実行
  3. どこにも参照されなくなった行を手動で削除する
  4. 制約を作成する

トリッキーな部分は制約の削除なので、誰かがそれを行う方法を知る必要がある場合に備えて、その方法を説明したいと思います。

  1. SHOW CREATE TABLE <Table Name>クエリを実行して、FOREIGN KEYの名前を確認します(下の画像の赤枠):

    ここに画像の説明を入力してください

  2. を実行しますALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign Key Name>。これにより、外部キー制約が削除されます。

  3. 関連するインデックスを(テーブル構造ページを介して)ドロップすると、完了です。

外部キーを再作成するには:

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

3

CASCADEを使用するだけ

TRUNCATE "products" RESTART IDENTITY CASCADE;

しかし、カスケード削除の準備をしてください)


3
OPはMySQLにタグを付けました。これはPostgresでは有効ですが、MySQLでは正しくありません。
ピーター

1

テーブルのデータベースエンジンが異なる場合、このエラーが発生するため、それらをInnoDBに変更します。

ALTER TABLE my_table ENGINE = InnoDB;

0

古い外部キーチェックの状態とSQLモードを取得することは、モデルをデータベースに同期するときにMysql Workbenchが行うようにテーブルを切り捨てる/ドロップする最良の方法です。

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;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.