🧚 잠깐! Beekeeper Studio는 빠르고 현대적인 오픈 소스 데이터베이스 GUI예요 다운로드
2026년 1월 13일 작성자: Matthew Rathbone

CREATE TABLE은 데이터베이스에 새 테이블을 추가해요. 테이블 이름을 정하고 컬럼을 나열하는데, 각 컬럼에는 데이터 타입과 값이 따라야 할 규칙(제약 조건)을 지정할 수 있어요. 예제는 PostgreSQL, MySQL, SQLite, SQL Server에서 동작해요.

CREATE TABLE 사용법

테이블 이름을 쓰고, 괄호 안에 컬럼을 쉼표로 구분해 나열하세요. 각 컬럼에는 이름과 데이터 타입, 그리고 필요하면 PRIMARY KEY, NOT NULL, UNIQUE, DEFAULT, CHECK 같은 제약 조건을 지정해요:

CREATE TABLE table_name (
    column_name data_type constraints,
    another_column data_type constraints
);
CREATE TABLE customers (
    id INTEGER PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE,
    country CHAR(2) DEFAULT 'US',
    signed_up DATE
);

INSERT INTO customers (id, name, email, signed_up)
VALUES (1, 'Ana Lima', 'ana@example.com', '2026-03-02');

SELECT * FROM customers;

-- Output:
-- id | name     | email           | country | signed_up
-- ---+----------+-----------------+---------+-----------
-- 1  | Ana Lima | ana@example.com | US      | 2026-03-02

새 테이블은 행을 삽입하기 전까지 비어 있어요. 이 insert에서는 country를 생략했기 때문에 행에 기본값인 US가 들어갔어요.

알아 둘 규칙

  • SQLite는 타입이나 길이를 강제하지 않아요. 다른 데이터베이스는 컬럼에 맞지 않는 값을 거부하지만, SQLite는 그대로 저장해요. 닫는 괄호 뒤에 STRICT를 붙이면 검사하게 할 수 있어요(strict 테이블은 INT, INTEGER, REAL, TEXT, BLOB, ANY 타입만 허용해요).
CREATE TABLE products (
    sku VARCHAR(5),
    quantity INTEGER
);

-- SQLite stores this row; other databases reject it with an error
INSERT INTO products VALUES ('LAMP-001', 'twelve');

SELECT sku, quantity FROM products;

-- Output (SQLite):
-- sku      | quantity
-- ---------+---------
-- LAMP-001 | twelve
  • 외래 키는 별도의 FOREIGN KEY 줄로 선언하세요. 컬럼 정의 안에 REFERENCES로 쓰지 마세요. MySQL 8은 그 짧은 형식을 받아들이지만 무시해 버려요. SQLite는 PRAGMA foreign_keys = ON;을 실행한 뒤에만 외래 키를 강제하며, 이 명령은 연결마다 실행해야 해요.
  • 테이블이 이미 있으면 CREATE TABLE은 실패해요. 대신 건너뛰려면 CREATE TABLE IF NOT EXISTS를 쓰세요.
  • MySQL에서는 TEXT 컬럼에 DEFAULT나 UNIQUE를 지정할 수 없어요. 여기 예제처럼 VARCHAR(n)을 사용하세요.

다른 문법

자동 증가 id는 데이터베이스마다 쓰는 방법이 달라요:

데이터베이스 자동 증가 id 컬럼
PostgreSQL id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY
MySQL id INT AUTO_INCREMENT PRIMARY KEY
SQLite id INTEGER PRIMARY KEY
SQL Server id INT IDENTITY(1,1) PRIMARY KEY

insert에서 id를 생략하면 데이터베이스가 다음 번호를 채워 넣어요.

SQL Server는 참/거짓 및 날짜-시간 컬럼에도 고유한 이름을 쓰고, IF NOT EXISTS도 없어요. BOOLEAN 대신 BIT(1과 0)를, 날짜와 시간에는 DATETIME2를 사용하고(SQL Server의 TIMESTAMP는 날짜가 아니라 행 버전 번호예요), 테이블을 만들기 전에 OBJECT_ID를 확인하세요:

-- SQL Server
IF OBJECT_ID('users', 'U') IS NULL
CREATE TABLE users (
    id INT IDENTITY(1,1) PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    is_active BIT NOT NULL DEFAULT 1,
    created_at DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE은 언제 사용하나요?

모든 테이블은 CREATE TABLE로 시작하지만, 어떤 컬럼과 제약 조건을 고르느냐에 따라 해결하는 문제가 달라져요.

새로운 종류의 데이터 저장하기

고객, 책, 청구서처럼 애플리케이션이 관리하는 대상마다 별도의 테이블을 두고, 각 정보마다 컬럼을 만들어 값에 맞는 타입을 지정해요.

모든 행에 고유 ID 부여하기

PRIMARY KEY는 두 행이 같은 식별자를 갖지 못하게 막아서, 언제든 정확히 한 행을 찾고 수정하고 연결할 수 있게 해 줘요. 데이터베이스가 행 번호를 매기게 하거나(위의 “다른 문법” 참고), 한 행을 식별하는 데 두 값이 필요하다면 두 컬럼을 조합하세요.

잘못되거나 누락된 데이터 막기

제약 조건은 규칙을 어기는 행을 거부해요. 필수 컬럼에는 NOT NULL, 이메일 주소 같은 값에는 UNIQUE, 허용 범위에는 CHECK를 쓰세요. DEFAULT는 insert에서 생략한 컬럼을 채워 줘요.

FOREIGN KEY는 컬럼이 다른 테이블의 행을 가리키게 해서, 주문이 존재하지 않는 고객을 참조하지 못하게 해요. ON DELETE CASCADE를 추가하면 부모 행을 삭제할 때 그 행을 가리키는 행들도 함께 삭제돼요.

쿼리 결과를 테이블로 저장하기

CREATE TABLE ... AS SELECT는 하나의 문으로 테이블을 만들고 쿼리 결과로 채워요. 스냅샷, 보고서용 테이블, 또는 변경하기 전 행을 백업할 때 사용하세요.

CREATE TABLE 실전 예제

오류 메시지는 PostgreSQL 기준이에요. 다른 데이터베이스도 같은 행을 거부하지만 메시지 문구는 달라요.

학생은 여러 과목을 듣고, 과목에는 여러 학생이 있어요. enrollments 테이블이 이 둘을 연결하고, 기본 키는 두 id의 조합이에요. 그래서 학생은 여러 과목에 등록할 수 있지만 같은 과목에 두 번 등록할 수는 없어요:

CREATE TABLE enrollments (
    student_id INTEGER NOT NULL,
    course_id INTEGER NOT NULL,
    enrolled_on DATE,
    PRIMARY KEY (student_id, course_id)
);

INSERT INTO enrollments VALUES (1, 101, '2026-09-01');
INSERT INTO enrollments VALUES (1, 102, '2026-09-01');
INSERT INTO enrollments VALUES (1, 101, '2026-09-08');
-- ERROR: duplicate key value violates unique constraint "enrollments_pkey"
-- DETAIL: Key (student_id, course_id)=(1, 101) already exists.

SELECT * FROM enrollments;

-- Output:
-- student_id | course_id | enrolled_on
-- -----------+-----------+------------
-- 1          | 101       | 2026-09-01
-- 1          | 102       | 2026-09-01

규칙을 따르는 가입 정보

모든 계정에는 다른 계정이 쓰지 않는 이메일 주소와 최소 1개의 시트가 필요해요. 새 계정은 시트 1개로 무료 등급에서 시작해요:

CREATE TABLE accounts (
    id INTEGER PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    tier VARCHAR(20) NOT NULL DEFAULT 'free',
    seats INTEGER NOT NULL DEFAULT 1 CHECK (seats > 0)
);

INSERT INTO accounts (id, email) VALUES (1, 'sam@example.com');

SELECT * FROM accounts;

-- Output:
-- id | email           | tier | seats
-- ---+-----------------+------+------
-- 1  | sam@example.com | free | 1

INSERT INTO accounts (id, email) VALUES (2, 'sam@example.com');
-- ERROR: duplicate key value violates unique constraint "accounts_email_key"

INSERT INTO accounts (id, email, seats) VALUES (3, 'kim@example.com', 0);
-- ERROR: new row ... violates check constraint "accounts_seats_check"

INSERT INTO accounts (id) VALUES (4);
-- ERROR: null value in column "email" ... violates not-null constraint

반드시 고객에 속해야 하는 주문

각 주문은 고객을 가리켜요. 외래 키는 존재하지 않는 고객의 주문을 거부하고, ON DELETE CASCADE는 고객이 삭제되면 그 고객의 주문도 함께 삭제해요. SQLite에서는 먼저 PRAGMA foreign_keys = ON;을 실행하세요.

CREATE TABLE customers (
    id INTEGER PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);

CREATE TABLE orders (
    id INTEGER PRIMARY KEY,
    customer_id INTEGER NOT NULL,
    total DECIMAL(10,2),
    FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE
);

-- Input: customers
-- id | name
-- ---+-----------
-- 1  | Ana Lima
-- 2  | Ben Okafor

-- Input: orders
-- id | customer_id | total
-- ---+-------------+------
-- 10 | 1           | 25.00
-- 11 | 1           | 60.00
-- 12 | 2           | 42.50

INSERT INTO orders VALUES (13, 99, 15.00);
-- ERROR: ... violates foreign key constraint "orders_customer_id_fkey"
-- DETAIL: Key (customer_id)=(99) is not present in table "customers".

DELETE FROM customers WHERE id = 1;

-- Output (orders after the DELETE):
-- id | customer_id | total
-- ---+-------------+------
-- 12 | 2           | 42.50

활성 고객 스냅샷

올해 주문한 고객을 별도 테이블로 복사해서, 새 주문이 들어와도 바뀌지 않는 캠페인 목록을 만들어요:

-- Input: customers
-- customer_id | name       | email             | last_order_date
-- ------------+------------+-------------------+----------------
-- 1           | Ana Lima   | ana@example.com   | 2026-03-18
-- 2           | Ben Okafor | ben@example.com   | 2025-11-02
-- 3           | Chloe Park | chloe@example.com | 2026-06-30
-- 4           | Dev Shah   | dev@example.com   | NULL

CREATE TABLE active_customers AS
SELECT customer_id, name, email
FROM customers
WHERE last_order_date >= '2026-01-01';

-- SQL Server has no CREATE TABLE ... AS. Use SELECT ... INTO:
SELECT customer_id, name, email
INTO active_customers
FROM customers
WHERE last_order_date >= '2026-01-01';

-- Output (active_customers):
-- customer_id | name       | email
-- ------------+------------+------------------
-- 1           | Ana Lima   | ana@example.com
-- 3           | Chloe Park | chloe@example.com

새 테이블에는 컬럼과 타입, 행이 복사되지만 기본 키나 다른 제약 조건은 복사되지 않아요. 필요하면 ALTER TABLE로 추가하세요.

CREATE TABLE 관련 추가 자료

이 블로그의 글:

공식 문서:

Beekeeper Studio는 무료 오픈 소스 데이터베이스 GUI예요

지금까지 써 본 SQL 쿼리 & 에디터 도구 중 최고예요. 데이터베이스 관리에 필요한 모든 게 다 있어요. - ⭐⭐⭐⭐⭐ Mit

Beekeeper Studio는 빠르고 직관적이며 사용하기 쉬워요. 다양한 데이터베이스를 지원하고 Windows, Mac, Linux에서 모두 잘 작동해요.

Beekeeper의 Linux 버전은 100% 모든 기능을 갖추고 있어요. 대충 만든 부분도, 빠진 기능도 없어요.

Beekeeper Studio 사용자 후기

★★★★★
"Beekeeper Studio가 기존 SQL 작업 방식을 완전히 대체했어요. 빠르고 직관적이라 데이터베이스 작업이 다시 즐거워졌어요."
— Alex K., 데이터베이스 개발자
★★★★★
"여러 데이터베이스 GUI를 써 봤지만, Beekeeper는 기능과 단순함 사이의 균형이 완벽해요. 그냥 잘 동작해요."
— Sarah M., 풀스택 엔지니어

SQL 작업 방식을 개선할 준비가 되셨나요?

download 무료 다운로드