DELETE — 테이블의 행 삭제

DELETE — 테이블의 행 삭제

DELETE 문으로 테이블에서 조건에 맞는 행을 지웁니다. 조건이 없으면 테이블의 모든 행이 삭제돼요. 삭제된 행을 기준으로 값을 돌려받고 싶다면 RETURNING 절을 쓸 수 있어요.

출처: PostgreSQL 문서

본문

개요 (Synopsis)

[ WITH [ RECURSIVE ] with_query [, ...] ]
DELETE FROM [ ONLY ] table_name [ * ] [ [ AS ] alias ]
[ USING from_item [, ...] ]
[ WHERE condition | WHERE CURRENT OF cursor_name ]
[ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ]
{ * | output_expression [ [ AS ] output_name ] } [, ...] ]

설명 (Description)

DELETE는 지정된 테이블에서 WHERE 절을 만족하는 행을 삭제해요. WHERE 절이 없으면 테이블의 모든 행을 지우는 효과가 있죠. 결과는 유효하지만 빈 테이블이 됩니다.

팁: 테이블에서 모든 행을 제거하는 더 빠른 방법으로는 TRUNCATE를 쓸 수 있어요.

다른 테이블의 정보를 이용해 테이블의 행을 지우는 방법은 두 가지가 있어요: 서브셀렉트(sub-select)를 쓰거나, USING 절에 추가 테이블을 지정하는 거죠. 어느 기법이 더 적절한지는 구체적인 상황에 달려 있습니다.

선택적인 RETURNING 절은 DELETE가 실제로 삭제한 각 행을 기준으로 값을 계산해 돌려주게 해요. 테이블의 컬럼이나 USING에 언급된 다른 테이블의 컬럼을 쓰는 어떤 식이라도 계산할 수 있어요. RETURNING 목록의 구문은 SELECT의 출력 목록과 동일합니다.

테이블에서 삭제하려면 그 테이블에 대한 DELETE 권한과, USING 절의 테이블 또는 조건에서 값을 읽는 모든 테이블에 대한 SELECT 권한이 있어야 해요.

매개변수 (Parameters)

  • with_query — WITH 절은 DELETE 질의에서 이름으로 참조할 수 있는 하나 이상의 서브쿼리를 지정하게 해줘요. 자세한 내용은 7.8절과 SELECT 문서를 참고하세요.
  • table_name — 행을 삭제할 테이블의 이름(선택적으로 스키마로 한정)이에요. 테이블 이름 앞에 ONLY를 지정하면, 일치하는 행이 그 이름의 테이블에서만 삭제돼요. ONLY를 지정하지 않으면 그 이름의 테이블에서 상속받은 어떤 테이블에서도 일치 행이 삭제됩니다. 선택적으로 테이블 이름 뒤에 *를 지정해 자손 테이블이 포함됨을 명시적으로 나타낼 수 있어요.
  • alias — 대상 테이블의 대체 이름이에요. 별칭이 주어지면 실제 테이블 이름을 완전히 가립니다. 예를 들어 DELETE FROM foo AS f라고 주어지면 DELETE 문의 나머지 부분은 이 테이블을 foo가 아니라 f로 참조해야 해요.
  • from_item — WHERE 조건에 다른 테이블의 컬럼이 나타나게 하는 테이블 식이에요. 이 구문은 SELECT 문의 FROM 절과 같아서, 예를 들어 테이블 이름에 대한 별칭을 지정할 수 있어요. 자기 조인(self-join)을 구성하려는 게 아니라면 대상 테이블을 from_item으로 반복하지 마세요(그 경우엔 from_item에 별칭을 붙여 나타나야 합니다).
  • condition — boolean 타입의 값을 돌려주는 식이에요. 이 식이 true를 돌려주는 행만 삭제됩니다.
  • cursor_name — WHERE CURRENT OF 조건에서 사용할 커서의 이름이에요. 삭제될 행은 이 커서에서 가장 최근에 가져온 행이에요. 커서는 DELETE 대상 테이블에 대한 그룹화 없는(non-grouping) 질의여야 합니다. WHERE CURRENT OF는 boolean 조건과 함께 지정할 수 없다는 점에 주의하세요. WHERE CURRENT OF와 커서 사용에 대한 더 자세한 내용은 DECLARE를 참고하세요.
  • output_alias — RETURNING 목록에서 OLD 또는 NEW 행에 대한 선택적인 대체 이름이에요. 기본적으로 대상 테이블의 예전 값은 OLD.column_name이나 OLD.*로, 새 값은 NEW.column_name이나 NEW.*로 써서 돌려받을 수 있어요. 별칭이 주어지면 이 이름들은 숨겨지고, 예전·새 행을 별칭으로 참조해야 합니다. 예를 들어 RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*처럼요.
  • output_expression — 각 행이 삭제된 뒤 DELETE 명령이 계산해 돌려줄 식이에요. 이 식은 table_name으로 이름 붙은 테이블이나 USING에 나열된 테이블의 어떤 컬럼 이름이든 쓸 수 있어요. 모든 컬럼을 돌려주려면 *를 쓰세요.
  • output_name — 돌려주는 컬럼에 쓸 이름이에요.

컬럼 이름이나 *는 OLD, NEW(또는 그에 대응하는 output_alias)로 한정해 예전 값이나 새 값이 돌아오게 할 수 있어요. 한정되지 않은 컬럼 이름, *, 혹은 대상 테이블 이름이나 별칭으로 한정한 컬럼 이름·*는 예전 값을 돌려줍니다.

단순한 DELETE의 경우 모든 새 값은 NULL이 돼요. 그러나 ON DELETE 규칙이 대신 INSERT나 UPDATE를 실행하게 하면 새 값이 NULL이 아닐 수 있습니다.

출력 (Outputs)

성공적으로 완료되면 DELETE 명령은 다음 형태의 명령 태그(command tag)를 돌려줘요.

DELETE count

count는 삭제된 행의 수예요. BEFORE DELETE 트리거가 삭제를 막아 조건에 맞는 행 수보다 적을 수 있다는 점에 주의하세요. count가 0이면 질의가 삭제한 행이 없다는 뜻입니다(이것은 오류로 간주되지 않아요).

DELETE 명령에 RETURNING 절이 있으면, 그 결과는 명령이 삭제한 행(들)에 대해 계산된, RETURNING 목록에 정의된 컬럼과 값을 담은 SELECT 문과 비슷해져요.

참고 사항 (Notes)

PostgreSQL은 USING 절에 다른 테이블을 지정해 WHERE 조건에서 그 테이블들의 컬럼을 참조하게 해 줍니다. 예를 들어 어떤 제작자가 만든 모든 영화를 삭제하려면:

DELETE FROM films USING producers
WHERE producer_id = producers.id AND producers.name = 'foo';

여기서 실제로 일어나는 일은 films와 producers 사이의 조인이며, 성공적으로 조인된 films 행이 모두 삭제 대상으로 표시되는 거예요. 이 구문은 표준이 아닙니다. 더 표준적인 방법은:

DELETE FROM films
WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo');

어떤 경우에는 조인 방식이 서브셀렉트 방식보다 쓰기 쉽거나 실행이 더 빠릅니다.

예시 (Examples)

뮤지컬을 제외한 모든 영화를 삭제하기:

DELETE FROM films WHERE kind <> 'Musical';

films 테이블 비우기:

DELETE FROM films;

완료된 작업을 삭제하면서 삭제된 행 전체 정보를 돌려받기:

DELETE FROM tasks WHERE status = 'DONE' RETURNING *;

커서 c_tasks가 현재 위치한 tasks의 행을 삭제하기:

DELETE FROM tasks WHERE CURRENT OF c_tasks;

DELETE에는 LIMIT 절이 없지만, UPDATE 문서에 설명된 것과 같은 방법으로 비슷한 효과를 얻을 수 있어요:

WITH delete_batch AS (
SELECT l.ctid FROM user_logs AS l
WHERE l.status = 'archived'
ORDER BY l.creation_date
FOR UPDATE
LIMIT 10000
)
DELETE FROM user_logs AS dl
USING delete_batch AS del
WHERE dl.ctid = del.ctid;

이 ctid 사용은 질의를 반복 실행해서 ctid가 바뀌는 문제를 피하기 때문에 안전합니다.

호환성 (Compatibility)

이 명령은 SQL 표준을 따르는데, USING과 RETURNING 절은 PostgreSQL 확장이며, DELETE와 함께 WITH를 쓸 수 있는 것도 마찬가지예요.

함께 보기 (See Also)

  • TRUNCATE — 테이블의 모든 행을 빠르게 제거

더 알아보기 (Learn more)

  • INSERT — 행을 테이블에 추가
  • UPDATE — 기존 행 수정
  • TRUNCATE — 테이블의 모든 행을 빠르게 비우기