Loading...
MySQL 9.5 Reference Manual 9.5의 15.2.2 DELETE Statement의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
DELETE는 테이블에서 row를 제거하는 DML statement입니다.
DELETE statement는 WITH clause로 시작할 수 있으며, 이를 통해 해당 DELETE 내에서 접근 가능한 공통 테이블 식을 정의할 수 있습니다. Section 15.2.20, “WITH (Common Table Expressions)”를 참조하십시오.
1DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [[AS] tbl_alias] 2 [PARTITION (partition_name [, partition_name] ...)] 3 [WHERE where_condition] 4 [ORDER BY ...] 5 [LIMIT row_count]
DELETE statement는 tbl_name 에서 row를 삭제하고 삭제된 row의 개수를 반환합니다. 삭제된 row의 개수를 확인하려면 Section 14.15, “Information Functions”에 설명된 ROW_COUNT() 함수를 호출하십시오.
선택적 WHERE clause의 조건은 삭제할 row를 식별합니다. WHERE clause가 없으면 모든 row가 삭제됩니다.
where_condition 은 삭제할 각 row에 대해 true로 평가되는 식입니다. 이는 Section 15.2.13, “SELECT Statement”에 설명된 대로 지정합니다.
ORDER BY clause를 지정하면, 해당 clause에서 지정한 순서대로 row가 삭제됩니다. LIMIT clause는 삭제할 수 있는 row의 개수에 제한을 둡니다. 이들 clause는 single-table delete에는 적용되지만, multi-table delete에는 적용되지 않습니다.
1DELETE [LOW_PRIORITY] [QUICK] [IGNORE] 2 tbl_name[.*] [, tbl_name[.*]] ... 3 FROM table_references 4 [WHERE where_condition] 5 6DELETE [LOW_PRIORITY] [QUICK] [IGNORE] 7 FROM tbl_name[.*] [, tbl_name[.*]] ... 8 USING table_references 9 [WHERE where_condition]
테이블에서 row를 삭제하려면 해당 테이블에 대한 DELETE 권한이 필요합니다. WHERE clause에 명시된 컬럼과 같이 읽기만 하는 컬럼에 대해서는 SELECT 권한만 필요합니다.
삭제된 row의 개수를 알 필요가 없다면, WHERE clause가 없는 DELETE statement보다 TRUNCATE TABLE statement를 사용해 테이블을 비우는 것이 더 빠릅니다. DELETE와 달리, TRUNCATE TABLE은 트랜잭션 내에서나 해당 테이블에 락이 걸린 상태에서는 사용할 수 없습니다. Section 15.1.42, “TRUNCATE TABLE Statement” 및 Section 15.3.6, “LOCK TABLES and UNLOCK TABLES Statements”를 참조하십시오.
delete 작업의 속도는 Section 10.2.5.3, “Optimizing DELETE Statements”에서 논의된 요인의 영향을 받을 수도 있습니다.
특정 DELETE statement에 너무 많은 시간이 걸리지 않도록 하려면, MySQL 고유의 LIMIT row_count clause를 사용하여 해당 DELETE에서 삭제할 row의 최대 개수를 지정할 수 있습니다. 삭제할 row의 개수가 이 limit보다 크면, 영향을 받은 row의 개수가 LIMIT 값보다 작아질 때까지 DELETE statement를 반복 실행하십시오.
서브쿼리에서 동일한 테이블을 select하면서 동시에 그 테이블에서 delete할 수는 없습니다.
DELETE는 PARTITION clause를 사용한 명시적인 파티션 선택을 지원하며, 이 clause는 삭제할 row를 선택할 파티션 또는 서브파티션 (또는 둘 다)의 이름을 쉼표로 구분한 목록을 받습니다. 목록에 포함되지 않은 파티션은 무시됩니다. p0라는 파티션을 가진 파티션 테이블 t가 있을 때, statement DELETE FROM t PARTITION (p0)을 실행하는 것은 ALTER TABLE t TRUNCATE PARTITION (p0)을 실행하는 것과 테이블에 미치는 효과가 동일합니다. 두 경우 모두 파티션 p0의 모든 row가 삭제됩니다.
PARTITION은 WHERE 조건과 함께 사용할 수도 있으며, 이 경우 조건은 나열된 파티션 내의 row에 대해서만 테스트됩니다. 예를 들어, DELETE FROM t PARTITION (p0) WHERE c < 5는 조건 c < 5가 true인 row만 파티션 p0에서 삭제합니다. 다른 파티션의 row는 검사되지 않으며, 따라서 이 DELETE의 영향을 받지 않습니다.
PARTITION clause는 multiple-table DELETE statement에서도 사용할 수 있습니다. FROM 옵션에 지정된 각 테이블마다 최대 한 번씩 이 옵션을 사용할 수 있습니다.
자세한 내용과 예시는 Section 26.5, “Partition Selection”을 참조하십시오.
AUTO_INCREMENT 컬럼의 최대 값을 포함하는 row를 삭제하더라도, MyISAM 또는 InnoDB 테이블에서는 그 값이 재사용되지 않습니다. autocommit 모드에서 DELETE FROM tbl_name (WHERE clause 없이)를 사용해 테이블의 모든 row를 삭제하면, InnoDB 및 MyISAM을 제외한 모든 스토리지 엔진에서 시퀀스가 처음부터 다시 시작됩니다. InnoDB 테이블의 경우 이 동작에 대한 몇 가지 예외가 있으며, 이는 Section 17.6.1.6, “AUTO_INCREMENT Handling in InnoDB”에서 설명합니다.
MyISAM 테이블의 경우, 다중 컬럼 키에서 보조 컬럼으로 AUTO_INCREMENT 컬럼을 지정할 수 있습니다. 이 경우, 시퀀스의 최상단에서 삭제된 값의 재사용이 MyISAM 테이블에서도 발생합니다. Section 5.6.9, “Using AUTO_INCREMENT”를 참조하십시오.
DELETE statement는 다음 modifier를 지원합니다:
LOW_PRIORITY modifier를 지정하면, 서버는 다른 클라이언트가 테이블에서 읽고 있지 않을 때까지 DELETE 실행을 지연시킵니다. 이는 MyISAM, MEMORY, MERGE처럼 테이블 단위 락만 사용하는 스토리지 엔진에만 영향을 줍니다.
MyISAM 테이블에서 QUICK modifier를 사용하면, 스토리지 엔진은 delete 동안 인덱스 리프를 병합하지 않는데, 이는 일부 종류의 delete 작업을 더 빠르게 만들 수 있습니다.
IGNORE modifier는 row 삭제 과정에서 발생하는 무시 가능한 오류를 MySQL이 무시하도록 합니다. (파싱 단계에서 발생한 오류는 일반적인 방식으로 처리됩니다.) IGNORE 사용으로 인해 무시된 오류는 경고로 반환됩니다. 자세한 내용은 The Effect of IGNORE on Statement Execution을 참조하십시오.
DELETE statement에 ORDER BY clause가 포함되어 있으면, row는 해당 clause에서 지정한 순서대로 삭제됩니다. 이는 주로 LIMIT과 함께 사용할 때 유용합니다. 예를 들어, 다음 statement는 WHERE clause와 일치하는 row를 찾고, 이를 timestamp_column으로 정렬한 다음, 첫 번째(가장 오래된) row를 삭제합니다:
1DELETE FROM somelog WHERE user = 'jcole' 2ORDER BY timestamp_column LIMIT 1;
ORDER BY는 또한 참조 무결성 위반을 피하기 위해 특정 순서로 row를 삭제하는 데 도움이 됩니다.
대용량 테이블에서 많은 row를 삭제하는 경우, InnoDB 테이블에 대해 락 테이블 크기를 초과할 수 있습니다. 이 문제를 피하거나, 단순히 테이블이 락된 상태로 유지되는 시간을 최소화하려면, (전혀 DELETE를 사용하지 않는) 다음 전략이 도움이 될 수 있습니다:
1INSERT INTO t_copy SELECT * FROM t WHERE ... ;
RENAME TABLE을 사용하여 원래 테이블을 다른 이름으로 옮기고 copy를 원래 이름으로 원자적으로 rename합니다:1RENAME TABLE t TO t_old, t_copy TO t;
1DROP TABLE t_old;
RENAME TABLE이 실행되는 동안 다른 세션은 이 작업에 관련된 테이블에 접근할 수 없으므로, rename 작업은 동시성 문제의 영향을 받지 않습니다. Section 15.1.41, “RENAME TABLE Statement”를 참조하십시오.
MyISAM 테이블에서 삭제된 row는 링크드 리스트로 유지되며, 이후 INSERT 작업은 이전 row 위치를 재사용합니다. 사용되지 않는 공간을 회수하고 파일 크기를 줄이려면, OPTIMIZE TABLE statement나 myisamchk 유틸리티를 사용해 테이블을 재구성하십시오. OPTIMIZE TABLE이 더 사용하기 쉽지만, myisamchk가 더 빠릅니다. Section 15.7.3.4, “OPTIMIZE TABLE Statement” 및 Section 6.6.4, “myisamchk — MyISAM Table-Maintenance Utility”를 참조하십시오.
QUICK modifier는 delete 작업 동안 인덱스 리프를 병합할지 여부에 영향을 줍니다. DELETE QUICK은 삭제된 row의 인덱스 값이 나중에 삽입된 row의 유사한 인덱스 값으로 대체되는 애플리케이션에 가장 유용합니다. 이 경우, 삭제로 인해 생긴 hole은 재사용됩니다.
삭제된 값이 다시 insert가 발생하는 인덱스 값 범위에 걸쳐 부족 채워진 인덱스 블록을 초래하는 경우에는, DELETE QUICK이 유용하지 않습니다. 이 경우 QUICK 사용으로 인해 인덱스 내의 공간이 낭비되며 회수되지 않은 상태로 남을 수 있습니다. 다음은 이러한 시나리오의 예입니다:
인덱스된 AUTO_INCREMENT 컬럼을 포함하는 테이블을 생성합니다.
테이블에 많은 row를 insert합니다. 각 insert는 인덱스의 상단(high end)에 추가되는 인덱스 값을 생성합니다.
DELETE QUICK을 사용해 컬럼 범위의 하단(low end)에 있는 row 블록을 삭제합니다.
이 시나리오에서 삭제된 인덱스 값과 연관된 인덱스 블록은 부족 채워진 상태가 되지만, QUICK 사용으로 인해 다른 인덱스 블록과 병합되지 않습니다. 새 insert가 발생해도 새로운 row의 인덱스 값이 삭제된 범위에 속하지 않으므로, 해당 블록은 부족 채워진 상태로 남습니다. 나중에 QUICK 없이 DELETE를 사용하더라도, 삭제된 인덱스 값 중 일부가 부족 채워진 블록 내부 또는 인접한 블록에 속하지 않는 한, 이 블록은 여전히 부족 채워진 상태로 남습니다. 이러한 상황에서 사용되지 않은 인덱스 공간을 회수하려면 OPTIMIZE TABLE을 사용하십시오.
테이블에서 많은 row를 삭제할 예정이라면, DELETE QUICK 후에 OPTIMIZE TABLE을 사용하는 것이 더 빠를 수 있습니다. 이 방식은 많은 인덱스 블록 병합 작업을 수행하는 대신 인덱스를 재구축합니다.
WHERE clause의 조건에 따라 한 개 이상의 테이블에서 row를 삭제하기 위해 DELETE statement에 여러 테이블을 지정할 수 있습니다. multiple-table DELETE에서는 ORDER BY나 LIMIT을 사용할 수 없습니다. table_references clause는 Section 15.2.13.2, “JOIN Clause”에 설명된 대로 조인에 포함되는 테이블을 나열합니다.
첫 번째 multiple-table syntax에서는 FROM clause 앞에 나열된 테이블의 일치하는 row만 삭제됩니다. 두 번째 multiple-table syntax에서는 USING clause 앞의 FROM clause에 나열된 테이블의 일치하는 row만 삭제됩니다. 이렇게 하면 여러 테이블에서 동시에 row를 삭제하면서, 검색에만 사용되는 추가 테이블을 둘 수 있습니다:
1DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 2WHERE t1.id=t2.id AND t2.id=t3.id;
또는:
1DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3 2WHERE t1.id=t2.id AND t2.id=t3.id;
이들 statement는 row를 검색할 때는 세 테이블 모두를 사용하지만, 일치하는 row는 테이블 t1과 t2에서만 삭제합니다.
위 예제는 INNER JOIN을 사용하지만, multiple-table DELETE statement는 SELECT statement에서 허용되는 다른 조인 타입(예: LEFT JOIN)도 사용할 수 있습니다. 예를 들어, t2에 일치하는 row가 존재하지 않는 t1의 row를 삭제하려면 LEFT JOIN을 사용합니다:
1DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
문법상, Access와의 호환성을 위해 각 tbl_name 뒤에 .*를 사용할 수 있습니다.
InnoDB 테이블에 대한 foreign key 제약 조건이 존재하는 경우, multiple-table DELETE statement를 사용하면 MySQL 옵티마이저가 parent/child 관계와 다른 순서로 테이블을 처리할 수 있습니다. 이 경우, statement는 실패하고 롤백됩니다. 대신, 단일 테이블에서 delete를 수행하고, 다른 테이블이 적절히 수정되도록 InnoDB가 제공하는 ON DELETE 기능에 의존해야 합니다.
참고
테이블에 대한 alias를 선언하는 경우, 해당 테이블을 참조할 때는 반드시 alias를 사용해야 합니다:
1DELETE t1 FROM test AS t1, test2 WHERE ...
multiple-table DELETE에서의 테이블 alias는 statement의 table_references 부분에서만 선언해야 합니다. 그 밖의 위치에서는 alias 참조는 허용되지만 alias 선언은 허용되지 않습니다.
Correct:
1DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2 2WHERE a1.id=a2.id; 3 4DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 5WHERE a1.id=a2.id;
Incorrect:
1DELETE t1 AS a1, t2 AS a2 FROM t1 INNER JOIN t2 2WHERE a1.id=a2.id; 3 4DELETE FROM t1 AS a1, t2 AS a2 USING t1 INNER JOIN t2 5WHERE a1.id=a2.id;
single-table DELETE statement에서도 테이블 alias가 지원됩니다.
15.2.1 CALL Statement
15.2.3 DO Statement