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

임시 테이블은 데이터베이스 세션이 유지되는 동안에만 존재하는 테이블이에요. 행을 채워 넣고 다른 테이블처럼 쿼리하면 되고, 연결을 끊으면 데이터베이스가 알아서 삭제해 줘요. 예제는 PostgreSQL, MySQL, SQLite, SQL Server에서 동작해요.

SQL 임시 테이블 사용법

임시 테이블은 일반 테이블처럼 만들되 TEMPORARY 키워드를 붙여요. 보통은 쿼리 결과로 바로 채워요:

CREATE TEMPORARY TABLE table_name AS
SELECT ...;

SQL Server는 예외예요. 이름 앞에 #를 붙이면 임시 테이블이 되고, SELECT ... INTO로 테이블을 만들면서 채워요.

-- Input: orders
-- id | customer | total | status
-- ---+----------+-------+---------
-- 1  | Maria    | 120   | paid
-- 2  | Tom      | 35    | refunded
-- 3  | Priya    | 89    | paid

CREATE TEMPORARY TABLE paid_orders AS
SELECT id, customer, total FROM orders WHERE status = 'paid';
-- SQL Server: SELECT id, customer, total INTO #paid_orders FROM orders WHERE status = 'paid';

SELECT * FROM paid_orders;  -- #paid_orders in SQL Server

-- Output:
-- id | customer | total
-- ---+----------+------
-- 1  | Maria    | 120
-- 3  | Priya    | 89

영구 테이블처럼 컬럼을 먼저 정의하고 나중에 행을 삽입할 수도 있어요:

CREATE TEMPORARY TABLE temp_students (  -- SQL Server: CREATE TABLE #temp_students (
  student_id INT PRIMARY KEY,
  first_name VARCHAR(50),
  last_name VARCHAR(50),
  age INT
);

INSERT INTO temp_students (student_id, first_name, last_name, age)
VALUES (1, 'John', 'Doe', 20);

SELECT * FROM temp_students;

-- Output:
-- student_id | first_name | last_name | age
-- -----------+------------+-----------+----
-- 1          | John       | Doe       | 20

알아 둘 규칙

  • 내 세션에서만 보여요. 다른 연결에서는 읽을 수 없고, 세션이 끝나면 데이터베이스가 삭제해요. 애플리케이션에서 커넥션 풀을 쓴다면 임시 테이블 생성과 쿼리를 같은 연결에서 하세요.
  • 같은 이름의 영구 테이블을 가려요. orders라는 임시 테이블을 만들면, 삭제할 때까지 orders에 대한 모든 쿼리가 임시 테이블을 읽어요. 그러니 겹치지 않는 이름을 고르세요. SQL Server의 # 접두사는 이 문제를 피해 줘요.
  • 두 번 만들면 실패해요. 한 세션에서 같은 스크립트를 두 번 실행하면 테이블이 이미 있어서 CREATE가 실패해요. 먼저 삭제하세요:
DROP TABLE IF EXISTS paid_orders;
-- In MySQL, DROP TEMPORARY TABLE IF EXISTS can never drop a permanent table by mistake
  • MySQL은 한 쿼리에서 임시 테이블을 두 번 읽지 못해요. 같은 임시 테이블에 대한 셀프 조인이나 서브쿼리는 ERROR 1137 (HY000): Can't reopen table 오류로 실패해요. 필요하면 복사본을 하나 더 만드세요.

다른 문법

  • CREATE TEMP TABLE은 PostgreSQL과 SQLite에서 쓸 수 있는 짧은 형태예요. MySQL은 지원하지 않아요.
  • SQL Server 전역 임시 테이블은 ##paid_orders처럼 해시 두 개로 시작해요. 모든 세션에서 읽을 수 있고, 만든 세션이 끝나면 SQL Server가 삭제해요.
  • CTE는 행이 쿼리 하나에만 필요할 때 같은 역할을 해요. 저장되는 게 없으니 삭제할 것도 없어요:
-- Input: the orders table above

WITH paid_orders AS (
  SELECT id, customer, total FROM orders WHERE status = 'paid'
)
SELECT * FROM paid_orders;

-- Output:
-- id | customer | total
-- ---+----------+------
-- 1  | Maria    | 120
-- 3  | Priya    | 89

임시 테이블은 언제 써야 할까요?

결과를 여러 쿼리에서 쓰고 싶지만 세션보다 오래 남길 필요는 없을 때 임시 테이블을 쓰세요.

같은 행을 여러 쿼리에서 재사용하기

이번 달 주문이나 진행 중인 프로젝트처럼 여러 리포트가 같은 필터링된 행에서 시작한다면, 매번 필터를 반복하지 말고 한 번 저장한 뒤 임시 테이블을 쿼리하세요.

필터링하거나 재사용할 합계 저장하기

GROUP BY로 한 번 집계하고 합계를 임시 테이블에 보관하세요. 그러면 다시 계산하지 않고도 필터링하거나 순위를 매기거나 평균과 비교할 수 있어요.

복잡한 쿼리를 단계별로 나누기

서브쿼리가 여러 겹인 쿼리는 읽기도 디버깅하기도 어려워요. 각 단계를 임시 테이블로 만들어 행을 확인한 뒤, 다음 단계에서 영구 테이블과 조인하세요.

복사본으로 변경 사항 시험하기

실제 데이터에 UPDATE나 DELETE를 실행하기 전에 테이블을 임시 테이블로 복사해서 먼저 실행해 보세요. 무엇이 바뀌는지 확인할 수 있고 원본은 그대로 남아요.

SQL 임시 테이블 실전 예제

SQL Server에서는 아래 임시 테이블을 CREATE TEMPORARY TABLE 대신 SELECT ... INTO #name으로 만드세요.

한 달 치 주문으로 리포트 두 번 만들기

10월 주문을 임시 테이블에 한 번 필터링해 두고, 원하는 만큼 리포트를 실행하세요:

-- Input: orders
-- id | customer | order_date | total
-- ---+----------+------------+------
-- 1  | Maria    | 2026-09-28 | 120
-- 2  | Tom      | 2026-10-02 | 35
-- 3  | Maria    | 2026-10-05 | 60
-- 4  | Priya    | 2026-10-09 | 89

CREATE TEMPORARY TABLE october_orders AS
SELECT id, customer, total
FROM orders
WHERE order_date >= '2026-10-01' AND order_date < '2026-11-01';

SELECT COUNT(*) AS order_count, SUM(total) AS revenue
FROM october_orders;

-- Output:
-- order_count | revenue
-- ------------+--------
-- 3           | 184

SELECT customer, SUM(total) AS spent
FROM october_orders
GROUP BY customer
ORDER BY spent DESC;

-- Output:
-- customer | spent
-- ---------+------
-- Priya    | 89
-- Maria    | 60
-- Tom      | 35

평균보다 많이 쓰는 고객 찾기

고객별 합계를 저장한 다음, 합계를 그 평균과 비교하세요:

-- Input: orders
-- id | customer | total
-- ---+----------+------
-- 1  | Maria    | 120
-- 2  | Tom      | 35
-- 3  | Maria    | 60
-- 4  | Priya    | 89
-- 5  | Priya    | 70

CREATE TEMPORARY TABLE customer_totals AS
SELECT customer, SUM(total) AS spent
FROM orders
GROUP BY customer;

SELECT customer, spent
FROM customer_totals
WHERE spent > (SELECT AVG(spent) FROM customer_totals)
ORDER BY spent DESC;

-- Output:
-- customer | spent
-- ---------+------
-- Maria    | 180
-- Priya    | 159

이 쿼리는 MySQL에서 실행되지 않아요. 한 쿼리에서 customer_totals를 두 번 읽을 수 없기 때문이에요(Can't reopen table). 평균을 먼저 별도 쿼리로 구하세요.

최근에 주문하지 않은 고객 찾기

한 단계에서 고객별 최근 주문을 구하고, 이를 고객 목록과 조인하세요. 테이블이 크다면 임시 테이블에 인덱스를 걸면 조인이 빨라져요:

-- Input: customers
-- id | name
-- ---+------
-- 1  | Maria
-- 2  | Tom
-- 3  | Priya

-- Input: orders
-- id | customer_id | order_date
-- ---+-------------+-----------
-- 1  | 1           | 2026-09-30
-- 2  | 2           | 2026-05-14
-- 3  | 1           | 2026-04-02

-- Step 1: each customer's latest order
CREATE TEMPORARY TABLE last_orders AS
SELECT customer_id, MAX(order_date) AS last_order
FROM orders
GROUP BY customer_id;

-- Step 2: on big tables, index the column you'll join on
CREATE INDEX idx_last_orders ON last_orders (customer_id);

-- Step 3: customers with no order since July 1
SELECT c.name, l.last_order
FROM customers c
LEFT JOIN last_orders l ON l.customer_id = c.id
WHERE l.last_order IS NULL OR l.last_order < '2026-07-01'
ORDER BY c.name;

-- Output:
-- name  | last_order
-- ------+-----------
-- Priya | NULL
-- Tom   | 2026-05-14

DELETE로 무엇이 삭제될지 확인하기

오래된 취소 주문을 정리하나요? 먼저 복사본에서 DELETE를 실행하고 남은 데이터를 확인하세요:

-- Input: orders
-- id | customer | status    | order_date
-- ---+----------+-----------+-----------
-- 1  | Maria    | cancelled | 2025-11-03
-- 2  | Tom      | shipped   | 2025-12-19
-- 3  | Priya    | cancelled | 2026-02-11
-- 4  | Maria    | shipped   | 2026-03-02

CREATE TEMPORARY TABLE orders_copy AS
SELECT * FROM orders;

DELETE FROM orders_copy
WHERE status = 'cancelled' AND order_date < '2026-01-01';

SELECT * FROM orders_copy;

-- Output:
-- id | customer | status    | order_date
-- ---+----------+-----------+-----------
-- 2  | Tom      | shipped   | 2025-12-19
-- 3  | Priya    | cancelled | 2026-02-11
-- 4  | Maria    | shipped   | 2026-03-02

-- The real table still has every row
SELECT COUNT(*) AS order_count FROM orders;
-- Output: 4

SQL 임시 테이블 더 읽어 보기

이 블로그에서:

공식 문서:

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 무료 다운로드