INSERT

INSERT — 테이블에 새 행을 추가

요약

[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
    [ OVERRIDING { SYSTEM | USER } VALUE ]
    { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
    [ ON CONFLICT [ conflict_target ] conflict_action ]
    [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

conflict_target은 다음 중 하나이다:

    ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
    ON CONSTRAINT constraint_name

conflict_action은 다음 중 하나이다:

    DO NOTHING
    DO UPDATE SET { column_name = { expression | DEFAULT } |
                    ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
                    ( column_name [, ...] ) = ( sub-SELECT )
                  } [, ...]
              [ WHERE condition ]

설명

INSERT 테이블에 새 행을 삽입한다. value 표현식에 지정된 하나 이상의 행을 삽입하거나, 쿼리 결과로부터 0개 이상의 행을 삽입할 수 있다.

대상 칼럼명은 임의의 순서대로 나열할 수 있다. 칼럼명을 지정하지 않는다면, 기본적으로 테이블의 모든 칼럼을 선언된 순서대로, 또는 VALUES 절이나 query에서 제공되는 칼럼이 N개 뿐이라면, 앞에서 부터 N개의 칼럼명을 사용한다. VALUES절이나 query에서 제공되는 값은 왼쪽부터 오른쪽의 순서대로 명시적 또는 암시적 칼럼 목록과 연결된다.

명시적 또는 암시적 칼럼 목록에 존재하지 않는 칼럼은, 그 기본값이 선언된 경우 기본값으로, 아니면 null로 채워진다.

어떠한 칼럼의 표현식이든 올바른 자료형이 아닐 경우, 자동 형변환을 시도한다.

ON CONFLICT는 unique 제약이나 exclusion 제약 위배 오류를 해소하기 위한, 대체 액션을 지정하기 위해 사용된다. (아래 ON CONFLICT Clause 참고)

선택적인 RETURNING 절은 causes INSERT로 하여금, 실제 삽입된 (또는, ON CONFLICT DO UPDATE 절이 사용된 경우, 업데이트 된) 각 행을 기반으로하는 값을 계산하고 반환하게 만든다. 이는 주로, 일련 번호와 같이 기본값으로 제공되는 값들을 알고 싶을 때 유용하다. 게다가, 테이블의 칼럼을 이용한 어떠한 표현식이든 가능하다. RETURNING 목록의 문법은 SELECT의 출력 목록과 동일하다. 성공적으로 삽입되거나 업데이트 된 행만 반환된다. 예를 들어, ON CONFLICT DO UPDATE ... WHERE절의 condition을 충족시키지 못해서 행이 잠겨졌지만 업데이트가 되지 않았을 경우, 해당 행은 반환되지 않는다.

테이블에 삽입하려면 해당 테이블에 대한 INSERT 권한이 있어야 한다. 또한, ON CONFLICT DO UPDATE가 존재한다면 UPDATE 권한도 있어야 한다.

칼럼 목록이 지정된 경우, 나열된 칼럼에 대한 INSERT 권한만 있으면 된다. 이와 유사하게, ON CONFLICT DO UPDATE가 지정된 경우, 업데이트 될 칼럼에 대한 UPDATE 권한만 있으면 된다. 다만, ON CONFLICT DO UPDATE의 경우, ON CONFLICT DO UPDATE 표현식이나 condition에서 값을 읽어야 하는 칼럼에 대한 SELECT 권한 또한 필요하다.

RETURNING 절을 사용하려면 RETURNING에 언급된 모든 칼럼에 대한 SELECT 권한이 필요하다. 물론, 쿼리로부터 행을 삽입하기 위해 query 절을 사용하는 경우라면, 쿼리 내에서 사용되는 모든 테이블과 칼럼에 대한 SELECT 권한이 필요하다.

매개 변수

Inserting

이 절에서는 새로운 행을 삽입할 때에만 사용되는 매개 변수를 다룬다. ON CONFLICT 절에서만 배타적으로 사용되는 매개 변수들은 별도로 설명한다.

with_query

WITH 절은, INSERT 쿼리 내에서 이름으로 참조될 수 있는, 하나 이상의 서브쿼리를 지정할 수 있게 한다. 자세한 내용은 7.8절SELECT를 참고하라.

query (SELECT 문) 또한 WITH 절을 포함할 수 있다. 이 경우, with_query의 두 집합 모두 query내에서 참조될 수 있지만, 두 번째 것은 중첩구조상 더 가까이 있을 경우에만 우선순위를 갖는다.

table_name

존재하는 (선택적으로 schema-qualified 된) 테이블의 이름.

alias

table_name을 대체하는 이름. 별칭이 제공되면, 테이블의 실제 이름을 완전히 숨기게 된다. 이는 특히 ON CONFLICT DO UPDATEexcluded로 명명된 테이블을 대상으로 할 때, 혹여 그 이름이 삽입하려는 행을 나타내는 특별한 테이블의 이름인 경우 유용하다.

column_name

table_name으로 명명된 테이블에 있는 칼럼명. 해당 칼럼명은, 필요한 경우 서브필드 명이나 array subscript로 제한될 수 있다. (복합 필드의 몇몇 필드에만 삽입하면 나머지 필드는 null로 채워진다.) ON CONFLICT DO UPDATE로 칼럼을 참조하는 경우, 대상 칼럼을 지정할 때 테이블 명을 포함하면 안된다. 예를 들어, INSERT INTO table_name ... ON CONFLICT DO UPDATE SET table_name.col = 1은 유효하지 않다. (이는 UPDATE의 일반적인 동작에 따른 것이다.)

OVERRIDING SYSTEM VALUE

If this clause is specified, then any values supplied for identity columns will override the default sequence-generated values.

For an identity column defined as GENERATED ALWAYS, it is an error to insert an explicit value (other than DEFAULT) without specifying either OVERRIDING SYSTEM VALUE or OVERRIDING USER VALUE. (For an identity column defined as GENERATED BY DEFAULT, OVERRIDING SYSTEM VALUE is the normal behavior and specifying it does nothing, but PostgreSQL allows it as an extension.)

OVERRIDING USER VALUE

If this clause is specified, then any values supplied for identity columns are ignored and the default sequence-generated values are applied.

This clause is useful for example when copying values between tables. Writing INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1 will copy from tbl1 all columns that are not identity columns in tbl2 while values for the identity columns in tbl2 will be generated by the sequences associated with tbl2.

DEFAULT VALUES

각 칼럼 값으로 DEFAULT라고 명시적으로 지정하는 경우, 모든 칼럼이 그 기본값으로 채워질 것이다.

expression

연관 칼럼에 할당할 수식이나 값.

DEFAULT

연관 칼럼이 자신의 기본값으로 채워질 것이다. An identity column will be filled with a new value generated by the associated sequence. For a generated column, specifying this is permitted but merely specifies the normal behavior of computing the column from its generation expression. (An OVERRIDING clause is not permitted in this form.)

query

삽입될 행을 제공하는 쿼리 (SELECT 문). 문법에 대한 설명은 SELECT문을 참고하라.

output_expression

각 행이 삽입되거나 업데이트 된 뒤, INSERT 명령에 의해 계산되어 반횐될 표현식. 해당 표현식은 table_name에 명명된 테이블에 있는 어떠한 칼럼명이라도 사용할 수 있다. 삽입되거나 업데이트 된 모든 칼럼을 반환하려면 *를 기입하라.

output_name

반환된 칼럼에 사용할 이름.

ON CONFLICT Clause

선택적 ON CONFLICT 절은 unique 위배나 exclusion 제약 위배 오류를 해소하기 위한 대체 액션을 지정한다. 삽입할 각 개별 행에 대해, 삽입이 진행되거나, 또는 conflict_target에 지정된 arbiter 제약이나 인덱스가 위배되었을 때, 대체 conflict_action이 수행된다. ON CONFLICT DO NOTHING은 대체 액션으로, 단순히 행이 삽입되는 것을 방지한다. ON CONFLICT DO UPDATE는 대체 액션으로, 삽입할 행과 충돌하는 기존 행을 업데이트 한다.

conflict_targetunique 인덱스 inference을 수행할 수 있다. inference을 수행할 때, 이는 하나 이상의 index_column_name 칼럼과 index_expression 표현식, 그리고 index_predicate로 구성된다. conflict_target에서 지정한 칼럼/표현식을, 순서와 관계없이 정확히 포함하는 모든 table_name unique 인덱스는, arbiter 인덱스로서 inferred (선택)된다 index_predicate가 지정되면, inference을 위한 추후 요구사항으로서, arbiter 인덱스를 충족해야 한다. 이는, 그 외의 모든 조건을 만족하는 인덱스가 존재한다면 non-partial unique 인덱스 (predicate가 없는 unique index)가 inferred 될 (그리고 ON CONFLICT에서 사용될) 것임을 의미한다. inference 시도가 실패할 경우, 오류가 발생한다.

ON CONFLICT DO UPDATE는 원자적 INSERT 또는 UPDATE 결과를 보장한다. 높은 동시성에도 불구하고, 독립적인 오류가 없다면 둘 중 한쪽의 결과가 보장된다. 이는 UPSERTUPDATE or INSERT로도 알려져 있다.

conflict_target

arbiter indexes를 선택함으로써, 어떤 충돌이 ON CONFLICT에서 대체 액션을 취할지 지정한다. unique 인덱스 inference을 수행하거나,명시적으로 constraint를 명명한다. ON CONFLICT DO NOTHING의 경우, conflict_target을 지정하는 것은 선택적이다. 이를 생략할 경우, 모든 사용 가능한 제약조건 (그리고 unique 인덱스)에 대한 충돌이 처리된다. ON CONFLICT DO UPDATE의 경우, conflict_target필수로 제공되어야 한다.

conflict_action

conflict_action은 대체 ON CONFLICT 액션을 지정한다. 이는, DO NOTHING이 될 수도 있고, 충돌시 유형에 따라 수행되는 UPDATE 액션의 정확한 세부사항을 지정하는 DO UPDATE 절이 될 수도 있다. ON CONFLICT DO UPDATE에 있는 SETWHERE절은 테이블명 (또는 별칭)을 이용해서 기존 행에 접근하거나, 특별한 excluded 테이블을 이용해서, 삽입을 위한 행에 접근할 수 있다. 관련된 excluded 칼럼을 읽어올 대상 테이블에 있는 모든 칼럼에 대해 SELECT 권한이 필요하다.

Note that the effects of all per-row BEFORE INSERT triggers are reflected in excluded values, since those effects may have contributed to the row being excluded from insertion.

index_column_name

table_name column의 이름. arbiter 인덱스를 infer 하기 위해 사용된다. CREATE INDEX 포맷을 따른다. index_column_name에 대한 SELECT 권한이 필요하다.

index_expression

index_column_name과 유사하나, (단순 칼럼이 아닌) 인덱스 정의 내에 나타나는, table_name 칼럼에 있는 infer 표현식에 사용된다. CREATE INDEX 포맷을 따른다. index_expression에 나타나는 모든 칼럼에 대한 SELECT 권한이 필요하다.

collation

지정되면, 관련된 index_column_name이나 index_expression이 inference 도중 일치하는 쌍을 찾을 때에 특정 collation을 사용하도록 지시한다. collations이 제약 위배가 발생하던 안하던 영향을 받지 않기 때문에, 일반적으로 생략된다. CREATE INDEX 포맷을 따른다.

opclass

지정되면, 관련된 index_column_name이나 index_expression이 inference 도중 일치하는 쌍을 찾기위해 특정 연산자 클래스를 사용하도록 지시한다. 동등 semantics가 자료형의 연산자 클래스를 통틀어서 거의 동일하기 때문에, 또한 정의된 unique 인덱스에 동등성에 대한 적절한 정의가 되어 있다고 충분히 신뢰할 수 있기 때문에 이는 일반적으로 생략된다. CREATE INDEX 포맷을 따른다.

index_predicate

partial unique 인덱스의 inference를 허용하기 위해 사용된다. 예측을 만족하는 (partial 인덱스일 필요는 없는) 모든 인덱는 inferred 될 수 있다. CREATE INDEX 포맷을 따른다. index_predicate 내에 나타나는 모든 칼럼에 대한 SELECT 권한이 필요하다.

constraint_name

제약이나 인덱스를 inferring 하는 대신에, 이름으로 arbiter constraint를 명시적으로 지정한다.

condition

boolean 자료형의 값을 반환하는 표현식 ON CONFLICT DO UPDATE 액션이 취해질 때 모든 행이 잠겨지더라도, 이 표현식으로 true가 반환되는 행만 업데이트 된다. 어떠한 충돌이 업데이트 후보로 식별된 이후, condition이 마지막으로 계산된다는 점에 주의하라.

ON CONFLICT DO UPDATE에서 exclusion 제약이 arbiter로서 지원되지 않는다는 점에 주의하라. 모든 경우에, NOT DEFERRABLE제약과 unique 인덱스만이 arbiter로서 지원된다.

ON CONFLICT DO UPDATE 절이 들어간 INSERTdeterministic 문장이다. 이는 해당 명령이, 존재하는 어떠한 단일 행에 대해 두번이상 영향을 줄수 없다는 걸 의미한다. 이러한 상황이 발생하면 cardinality violation error가 발생할 것이다. 삽입하려는 행은 arbiter 인덱스나 제약조건에 의해 제약된 속성의 측면에서, 서로 중복되어서는 안된다.

Note that it is currently not supported for the ON CONFLICT DO UPDATE clause of an INSERT applied to a partitioned table to update the partition key of a conflicting row such that it requires the row be moved to a new partition.

작은 정보

ON CONFLICT ON CONSTRAINT constraint_name으로 제약조건을 직접 명명하는 것보다 unique 인덱스 inference 를 사용하는 편이 더 좋다. Inference 는, 덮어쓰는 방식으로, 예를 들면 교체될 인덱스를 drop하기 전에 CREATE UNIQUE INDEX ... CONCURRENTLY를 사용하는 식으로, 기반 인덱스가 더 많이 또는 덜 동일한 인덱스로 교체되더라도 문제없이 동작할 것이다.

Outputs

성공적으로 완료되면, INSERT 명령은 아래 형식의 명령 태그를 반환한다.

INSERT oid count

The count is the number of rows inserted or updated. oid is always 0 (it used to be the OID assigned to the inserted row if count was exactly one and the target table was declared WITH OIDS and 0 otherwise, but creating a table WITH OIDS is not supported anymore).

INSERT 명령에 RETURNING 절이 포함되어 있다면, 그 결과는, 해당 명령에서 삽입되거나 업데이트 되는 행에 대해 계산된 값이며, RETURNING 목록에 정의된 칼럼 및 값을 포함하는SELECT문의 결과와 유사하다.

Notes

If the specified table is a partitioned table, each row is routed to the appropriate partition and inserted into it. If the specified table is a partition, an error will occur if one of the input rows violates the partition constraint.

예제

films 테이블에 단일 행을 삽입한다:

INSERT INTO films VALUES
    ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');

이 예제에서, len 칼럼은 생략되었고, 따라서 기본 값을 갖게 된다:

INSERT INTO films (code, title, did, date_prod, kind)
    VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');

이 예제는 데이터 칼럼에 값을 지정하지 않고 DEFAULT 절을 사용한다:

INSERT INTO films VALUES
    ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes');
INSERT INTO films (code, title, did, date_prod, kind)
    VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama');

기본 값만으로 구성된 행을 삽입한다:

INSERT INTO films DEFAULT VALUES;

다행 VALUES 문법을 사용하여 다수의 행을 삽입한다:

INSERT INTO films (code, title, did, date_prod, kind) VALUES
    ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
    ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');

이 예제는, films과 동일한 칼럼 레이아웃을 갖는 tmp_films 테이블로부터 films 테이블로 몇몇 행을 삽입한다:

INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';

이 예제는 배열 칼럼에 삽입한다:

-- Create an empty 3x3 gameboard for noughts-and-crosses
INSERT INTO tictactoe (game, board[1:3][1:3])
    VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}');
-- The subscripts in the above example aren't really needed
INSERT INTO tictactoe (game, board)
    VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}');

단일 행을 distributors 테이블에 삽입하고, DEFAULT 절에 의해 생성된 일련번호를 반환한다:

INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets')
   RETURNING did;

Acme Corporation의 계정을 관리하는 salesperson의 sales count를 증가시키고, 로그 테이블에, 업데이트된 행 전체와 현재 시각을 기록한다:

WITH upd AS (
  UPDATE employees SET sales_count = sales_count + 1 WHERE id =
    (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation')
    RETURNING *
)
INSERT INTO employees_log SELECT *, current_timestamp FROM upd;

새distributors를 적절하게 삽입 또는 업데이트 한다. did 칼럼에 나타나는 값을 제약하는 unique 인덱스가 정의되었다고 가정한다. 삽입에 사용되는 값을 참조하기 위해 특별한 excluded 테이블이 사용되었음에 주의하라:

INSERT INTO distributors (did, dname)
    VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
    ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;

distributor를 삽입하거나, excluded 행 (행 삽입 트리거가 발생한 전후로 제약 칼럼(들)이 일치하는 행)이 이미 존재할 경우 삽입할 행에 대해 아무 작업도 하지 않는다. 예제에서는 did 칼럼에 나타나는 값을 제약하는 unique 인덱스가 정의되어있다고 가정한다:

INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
    ON CONFLICT (did) DO NOTHING;

신규 distributors를 적절하게 삽입 또는 업데이트 한다. 예제에서는, did 칼럼에 나타나는 값을 제약하는 unique 인덱스가 정의되어있다고 가정한다. 실제 업데이트 되는 행을 제한하기 위해 WHERE 절이 사용되었다. (그렇더라도, 업데이트 되지 않은 기존의 행은 여전히 잠겨있을 것이다):

-- 특정 ZIP code에 기반해서 기존 distributor는 업데이트 하지 않는다.
INSERT INTO distributors AS d (did, dname) VALUES (8, 'Anvil Distribution')
    ON CONFLICT (did) DO UPDATE
    SET dname = EXCLUDED.dname || ' (formerly ' || d.dname || ')'
    WHERE d.zipcode <> '21201';

-- 문장 내에서 제약조건을 직접 명명한다. (DO NOTHING 액션을 사용하기 위해
-- 관련된 인덱스를 사용한다)
INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design')
    ON CONFLICT ON CONSTRAINT distributors_pkey DO NOTHING;

가능하다면 신규 distributor를 삽입한다. 그렇지 않은 경우 DO NOTHING. 예제에서는, is_active Boolean 칼럼이 true인 행의 부분집합에 대해 did 칼럼에 나타나는 값을 제약하는 unique 인덱스가 정의되었다고 가정한다:

-- 이 문장은 "WHERE is_active"의 서술부로
-- "did"에 대한 partial unique 인덱스를 infer 할 수 있지만,
-- 또한 "did" 제약에 일반적인 unique 제약을 사용할 수도 있다
INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International')
    ON CONFLICT (did) WHERE is_active DO NOTHING;

Compatibility

INSERTRETURNING 절이 PostgreSQL 확장이며, INSERTWITH를 사용할 수 있고, ON CONFLICT에 대체 액션을 지정할 수 있다는 점을 제외하면, SQL 표준을 따른다. 또한, 칼럼 명 목록이 생략될 경우 모든 칼럼이 VALUES 절이나 query로 채워지진 않는다는 점은, 표준에서 허용되지 않는 점이다.

The SQL standard specifies that OVERRIDING SYSTEM VALUE can only be specified if an identity column that is generated always exists. PostgreSQL allows the clause in any case and ignores it if it is not applicable.

query의 제약사항은 SELECT에 문서화 되어 있다.