본문 바로가기
WIKI 기술 지식 베이스

INSERT

원문 보기 위키 갱신

테이블에 새 행을 추가하는 INSERT 문이에요. 리터럴 값을 넣을 수도 있고, 다른 쿼리의 결과를 복사하거나 컬럼 기본값으로 채울 수도 있어서 상황에 맞게 골라 쓸 수 있어요.

출처: 문서

본문

INSERT는 지정한 테이블에 하나 이상의 행을 추가해요. 행은 리터럴 값으로 지정하거나, 다른 쿼리에서 복사하거나, 컬럼 기본값으로 생성할 수 있어요.

Syntax

INSERT [OR conflict_action] INTO table_name [(column_name [, ...])]
  VALUES (expression [, ...]) [, (expression [, ...]) ...]
  [RETURNING result_column [, ...]];

INSERT [OR conflict_action] INTO table_name [(column_name [, ...])]
  select_statement
  [RETURNING result_column [, ...]];

INSERT [OR conflict_action] INTO table_name [(column_name [, ...])]
  DEFAULT VALUES
  [RETURNING result_column [, ...]];

Parameters

Parameter Type Description
conflict_action keyword REPLACE, IGNORE, ABORT, ROLLBACK, FAIL 중 하나예요. 제약 조건 위반 시 동작을 제어해요.
table_name identifier 행을 삽입할 테이블이에요.
column_name identifier 값을 할당할 컬럼이에요. 나열하지 않은 컬럼은 기본값 또는 NULL을 받아요.
expression expression 삽입할 값이거나, 컬럼 기본값을 쓰겠다는 DEFAULT 키워드예요. 대상 컬럼의 위치나 이름과 일치해야 해요.
select_statement SELECT query 결과 행이 테이블에 삽입되는 쿼리예요.
result_column expression 삽입된 각 행마다 돌려줄 컬럼이나 표현식이에요.

Description

INSERT는 지정한 테이블에 새 행을 추가해요. 세 가지 형태가 있어요.

  • VALUES: 명시적인 값으로 하나 이상의 행을 삽입해요.
  • SELECT: 쿼리의 결과 집합을 삽입해요.
  • DEFAULT VALUES: 모든 컬럼이 기본값(기본값이 정의되어 있지 않으면 NULL)을 사용하는 한 개의 행을 삽입해요.

컬럼 목록을 지정하면 나열한 컬럼만 명시적인 값을 받아요. 나머지 컬럼은 기본값 또는 NULL을 사용해요. 컬럼 목록을 지정하지 않으면 테이블의 모든 컬럼에 대해, 컬럼이 정의된 순서대로 값을 제공해야 해요.

Inserting Rows

Single Row

INSERT INTO employees (name, department, salary)
VALUES ('Alice', 'Engineering', 95000);

Multiple Rows

쉼표로 구분된 여러 개의 괄호 그룹을 나열해요.

INSERT INTO employees (name, department, salary) VALUES
  ('Bob', 'Design', 82000),
  ('Carol', 'Engineering', 97000),
  ('Dave', 'Marketing', 74000);

All Columns

컬럼 목록을 생략할 때는 테이블 정의 순서대로 모든 컬럼에 값을 제공해야 해요.

-- employees 테이블에 id, name, department, salary 컬럼이 있다고 가정해요
INSERT INTO employees VALUES (1, 'Alice', 'Engineering', 95000);

INSERT INTO ... SELECT

SELECT 문의 결과를 삽입해요. SELECT가 돌려주는 컬럼 수는 대상 컬럼 수와 일치해야 해요.

INSERT INTO archive_employees (name, department, salary)
SELECT name, department, salary
FROM employees
WHERE termination_date IS NOT NULL;

SELECT에는 WHERE, JOIN, GROUP BY, ORDER BY, LIMIT, UNION, 서브쿼리 등 어떤 유효한 절도 포함될 수 있어요.

INSERT INTO monthly_summary (department, headcount, total_salary)
SELECT department, COUNT(*), SUM(salary)
FROM employees
GROUP BY department;

DEFAULT VALUES

모든 컬럼이 기본값을 받는 한 개의 행을 삽입해요. 명시적인 DEFAULT 정의가 없는 컬럼은 NULL을 받아요. INTEGER PRIMARY KEY 컬럼은 자동 생성된 rowid를 받아요.

CREATE TABLE audit_log (
  id INTEGER PRIMARY KEY,
  created_at TEXT DEFAULT (datetime('now')),
  action TEXT DEFAULT 'unknown'
);

INSERT INTO audit_log DEFAULT VALUES;
-- (auto_id, current_timestamp, 'unknown')이 삽입돼요

Column Default Values

컬럼 목록을 지정하면 생략된 컬럼은 기본값을 사용해요.

CREATE TABLE tasks (
  id INTEGER PRIMARY KEY,
  title TEXT NOT NULL,
  status TEXT DEFAULT 'pending',
  priority INTEGER DEFAULT 0,
  created_at TEXT DEFAULT (datetime('now'))
);

-- status, priority, created_at은 기본값을 사용해요
INSERT INTO tasks (title) VALUES ('Review pull request');

DEFAULT Keyword in VALUES

**Turso 확장** -- 이 기능은 SQL 표준(SQL:2016)을 따르지만 SQLite는 지원하지 않아요.

VALUES 목록에서 임의의 값 표현식 대신 DEFAULT 키워드를 쓸 수 있어요. 이 키워드는 CREATE TABLE 문에서 정의한 컬럼의 기본값으로 해석되고, 기본값이 정의되어 있지 않으면 NULL이 돼요. 여러 행을 삽입하면서 행마다 서로 다른 컬럼에 기본값이 필요할 때 특히 유용한데, 이런 경우는 컬럼 목록에서 컬럼을 생략하는 방식으로는 만들 수 없어요.

CREATE TABLE tasks (
  id INTEGER PRIMARY KEY,
  title TEXT NOT NULL,
  status TEXT DEFAULT 'pending',
  priority INTEGER DEFAULT 0
);

-- 특정 컬럼에 DEFAULT를 사용해요
INSERT INTO tasks (id, title, status, priority)
VALUES (1, 'Fix bug', DEFAULT, 5);
-- (1, 'Fix bug', 'pending', 5)가 삽입돼요

-- 행마다 서로 다른 컬럼이 DEFAULT를 사용해요
INSERT INTO tasks (id, title, status, priority) VALUES
  (2, 'Write docs', DEFAULT, 3),
  (3, 'Code review', 'in_progress', DEFAULT);
-- (2, 'Write docs', 'pending', 3)이 삽입돼요
-- (3, 'Code review', 'in_progress', 0)이 삽입돼요

DEFAULT 키워드는 INSERT VALUES 목록 안에서만 유효해요. 다른 맥락(SELECT, WHERE, UPDATE)에서 쓰면 오류가 발생해요.

Conflict Handling

OR 절은 INSERT가 유니크(uniqueness) 또는 NOT NULL 제약 조건을 위반했을 때 어떤 일이 벌어지는지 지정해요.

Action Behavior
ABORT 현재 문장을 롤백하고 오류를 돌려줘요. 같은 INSERT 안에서 이미 삽입된 행은 되돌려져요. 이것이 기본값이에요.
ROLLBACK 트랜잭션 전체를 롤백하고 오류를 돌려줘요.
FAIL 실행을 멈추고 오류를 돌려줘요. 실패 전에 이 문장이 삽입한 행은 그대로 유지돼요.
IGNORE 위반을 일으킨 행을 건너뛰고 다음 행으로 계속 진행해요.
REPLACE 충돌한 행을 삭제하고 그 자리에 새 행을 삽입해요.
-- UNIQUE 제약을 위반하는 행은 건너뛰어요
INSERT OR IGNORE INTO employees (id, name, department, salary)
VALUES (1, 'Alice', 'Engineering', 95000);

-- 충돌 시 기존 행을 대체해요
INSERT OR REPLACE INTO employees (id, name, department, salary)
VALUES (1, 'Alice', 'Engineering', 105000);

-- 충돌 시 이 문장만 롤백해요
INSERT OR ABORT INTO employees (id, name, department, salary)
VALUES (1, 'Alice', 'Engineering', 95000);
특정 제약 조건을 기준으로 더 세밀한 충돌 처리를 하려면 [ON CONFLICT](/sql-reference/statements/upsert) 절(UPSERT)을 사용해 보세요. 어떤 제약 조건이 위반됐는지에 따라 다른 동작을 취할 수 있어요.

RETURNING Clause

실제로 삽입된 행의 데이터를 돌려줘요. 자동 증가 ID나 평가된 기본값처럼 생성된 값을 곧바로 가져올 때 유용해요.

INSERT INTO employees (name, department, salary)
VALUES ('Eve', 'Engineering', 91000)
RETURNING id, name;
-- Returns: 5|Eve

RETURNING은 삽입된 행의 컬럼을 참조할 수 있는 어떤 표현식도 받아들여요.

INSERT INTO employees (name, department, salary)
VALUES ('Frank', 'Design', 78000)
RETURNING id, name, salary * 12 AS annual_salary;
-- Returns: 6|Frank|936000

RETURNING with Multiple Rows

INSERT INTO employees (name, department, salary) VALUES
  ('Grace', 'Engineering', 102000),
  ('Hank', 'Marketing', 68000)
RETURNING id, name, department;
-- 삽입된 행마다 한 행씩 돌려줘요

RETURNING *

삽입된 행의 모든 컬럼을 돌려줘요.

INSERT INTO employees (name, department, salary)
VALUES ('Ivy', 'Product', 88000)
RETURNING *;

Examples

Insert with Subquery Values

INSERT INTO department_stats (department, avg_salary)
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING COUNT(*) >= 3;

Insert with Conflict Handling and RETURNING

INSERT OR REPLACE INTO settings (key, value)
VALUES ('theme', 'dark'), ('locale', 'en-US')
RETURNING key, value;

Archival Pattern

-- 행을 아카이브로 복사한 다음 원본을 삭제해요
INSERT INTO orders_archive
SELECT * FROM orders WHERE order_date < '2023-01-01';

DELETE FROM orders WHERE order_date < '2023-01-01';

See Also

더 알아보기 (Learn more)