외래 키 제한 테이블을 자르는 방법?


648

왜하지 않는 TRUNCATE 에 대한 mygroup작업은? 내가 가지고 있지만 ON DELETE CASCADE SET:

오류 1701 (42000) : 외래 키 제약 조건 ( mytest. instance, CONSTRAINT instance_ibfk_1FOREIGN KEY ( GroupID) REFERENCES 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;

답변:


1000

당신은 할 수없는 TRUNCATE그것을 적용 FK 제약 조건이있는 테이블 ( TRUNCATE동일하지 않습니다 DELETE).

이 문제를 해결하려면 다음 솔루션 중 하나를 사용하십시오. 두 가지 모두 데이터 무결성을 손상시킬 위험이 있습니다.

옵션 1:

  1. 구속 조건 제거
  2. 행하다 TRUNCATE
  3. 이제 아무데도 참조가 없는 행을 수동으로 삭제하십시오.
  4. 구속 조건 작성

옵션 2 : 답변 에서 user447951제안 함

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

46
@barjonah : 실제로 데이터 무결성을 손상시킬 수 있습니다 ( stackoverflow.com/questions/5452760/… 참조 ). 따라서 현실 세계에서 "빛"이라고 부르는 것은 나쁜 습관으로 간주됩니다. 추신 : downvote 주셔서 감사합니다
zerkms

1
여기에 고아가 외부 키를 찾을 수있는 아주 좋은 방법입니다 (데이터 무결성을 복원) http://stackoverflow.com/a/12085689/997776
SandorRacz

자르기 전에 외래 키를 비활성화하는 것도 좋은 방법입니다. 나는 소스에서 성공했습니다 : stackoverflow.com/questions/8641703/…
Dung

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

5
PHPMYADMIN에서 사용하는 경우 동일한 SQL 창에서 모든 트랜잭션을 사용하는 경우에만 작동합니다 (a로 구분 ;). 이것은 각각의 새로운 웹 SQL 호출이 1로 재설정되기 때문입니다 FOREIGN_KEY_CHECKS.
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

이것은 당신이하고 싶은 모든 일이라면 좋지만 DELETE행이 너무 많으면 로그를 치는 반면 TRUNCATE데이터를 찢어 버리기 때문에 너무 잔인 할 수 있습니다 . 사용 사례에 따라 다릅니다.
Jeff

1
delete 문을 사용할 때 오류 1175가보고됩니다. 안전한 업데이트 모드를 사용 중입니다. SET SQL_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
나는 그것을 시도했다, 다음과 같은 오류가 나타났습니다 : 오류 코드 : 1142. DELETE 명령이 'mytable'테이블에 대한 'root'@ 'localhost'사용자에게 거부되었습니다.
AAEM

또는 그냥 삭제mytable
Miloslav Milo Janoušek

자동 증분은 재설정되지 않습니다.
vivek_23

13

당으로 MySQL의 문서 , TRUNCATE는 외래 키 관계가있는 테이블에 사용할 수 없습니다. 완전한 대안 AFAIK가 없습니다.

제약 조건을 삭제해도 여전히 ON DELETE 및 ON UPDATE가 호출되지 않습니다. ATM에서 생각할 수있는 유일한 솔루션은 다음 중 하나입니다.

  • 모든 행을 삭제하고 외래 키를 삭제하고 자르고 키를 다시 만듭니다.
  • 모든 행을 삭제하고 auto_increment를 재설정하십시오 (사용 된 경우).

MySQL의 TRUNCATE는 아직 완전한 기능이 아닙니다 (트리거를 호출하지도 않습니다). 의견보기


7
MySQL TRUNCATE이 불완전하다는 점에 대한 참고 사항 -truncate는 트리거 등을 호출하지 않아야합니다 DELETE. 행에 구애받지 않으므로 트리거 호출 또는 외래 키 검사와 같은 행 관련 작업을 수행 할 수 없습니다. OracleSql Server 에서 동일한 방식으로 작동합니다 .
Simon Mᶜ 켄지

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. TRUNCATE 수행
  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에서는 올바르지 않습니다.
Peter

1

테이블의 데이터베이스 엔진이 다르면이 오류가 발생하므로 InnoDB로 변경하십시오.

ALTER TABLE my_table ENGINE = InnoDB;

0

모델을 데이터베이스와 동기화하는 동안 Mysql Workbench가 수행하는 것처럼 이전 외래 키 확인 상태와 SQL 모드를 얻는 것이 테이블을 자르거나 삭제하는 가장 좋은 방법입니다.

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.