본문으로 건너뛰기
IntoSQL 홈

데이터베이스를 다른 데이터베이스로 변환

mysqldump, mariadb-dump, pg_dump, SSMS, SQL Developer, SQLcl 덤프나 SQLite .db 파일을 놓으면, 같은 테이블, 키, 인덱스, 데이터를 담은 PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle 스크립트를 받아요. 모든 변경은 보고서에 나오고, 덤프는 컴퓨터 밖으로 나가지 않아요.

내 파일
sqlshop_2024.sql샘플 파일, 5.1kB
내 데이터베이스

18개 행 변환, 수정 8개, 거부 없음

보기

shop_2024.sql의 테이블MySQL 8.0.46 덤프 · mysqldump(으)로 작성됨 · utf8mb4

  • customers8개 행3
    7개 열
    idbigint not null
    namevarchar(100) not null
    emailvarchar(150) not null
    countryvarchar(2) not null
    is_activeboolean not null
    signed_update
    created_attimestamptz(0) not null
  • orders10개 행5
    9개 열
    idbigint not null
    customer_idbigint not null
    statustext not null
    totalnumeric(10,2) not null
    itemsinteger not null
    ordered_attimestamp(0) not null
    shipped_attimestamp(0)
    notevarchar(255)
    updated_attimestamptz(0) not null
-- Written by IntoSQL from a MySQL dump. Load it with: psql -v ON_ERROR_STOP=1 -f <file>
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET synchronous_commit = off;
SET maintenance_work_mem = '512MB';

CREATE TABLE customers (
    id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    name varchar(100) NOT NULL,
    email varchar(150) NOT NULL,
    country varchar(2) DEFAULT 'US' NOT NULL,
    is_active boolean DEFAULT true NOT NULL,
    signed_up date,
    created_at timestamptz(0) DEFAULT CURRENT_TIMESTAMP NOT NULL,
    CONSTRAINT customers_id_check CHECK (id >= 0)
);

CREATE TABLE orders (
    id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    customer_id bigint NOT NULL,
    status text DEFAULT 'pending' NOT NULL,
    total numeric(10,2) NOT NULL,
    items integer DEFAULT 1 NOT NULL,
    ordered_at timestamp(0) NOT NULL,
    shipped_at timestamp(0),
    note varchar(255),
    updated_at timestamptz(0) DEFAULT CURRENT_TIMESTAMP NOT NULL,
    CONSTRAINT orders_id_check CHECK (id >= 0),
    CONSTRAINT orders_customer_id_check CHECK (customer_id >= 0),
    CONSTRAINT orders_status_check CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled', '')),
    CONSTRAINT orders_items_check CHECK (items >= 0)
);

COPY customers (id, name, email, country, is_active, signed_up, created_at) FROM stdin;
1	Ana Martínez	ana@example.com	MX	t	2023-01-15	2023-01-15 10:24:00+00:00
2	Zoë Müller	zoe@example.de	DE	t	2023-02-03	2023-02-03 08:11:42+00:00
3	José Peña	jose@example.es	ES	f	2023-03-21	2023-03-21 19:05:17+00:00
4	李雷	lilei@example.cn	CN	t	2023-05-09	2023-05-09 02:40:00+00:00
5	Noah O'Brien	noah@example.ie	IE	t	\N	2023-06-30 14:00:00+00:00
6	Amélie Laurent	amelie@example.fr	FR	t	2024-01-02	2024-01-02 09:30:00+00:00
7	Ravi Patel	ravi@example.in	IN	f	2024-02-29	2024-02-29 23:59:59+00:00
8	Sofia Rossi 🌻	sofia@example.it	IT	t	2024-04-12	2024-04-12 12:12:12+00:00
\.

COPY orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, updated_at) FROM stdin;
1	1	shipped	129.90	3	2024-03-01 10:00:00	2024-03-02 16:30:00	\N	2024-03-02 16:30:00+00:00
2	2	paid	54.00	1	2024-03-02 11:15:00	\N	Gift wrap 🎁	2024-03-02 11:20:00+00:00
3	1	cancelled	12.50	1	2024-03-03 09:45:00	\N	Customer changed their mind	2024-03-03 10:00:00+00:00
4	4	shipped	980.00	12	2024-03-05 02:10:00	2024-03-07 08:00:00	请小心轻放	2024-03-07 08:00:00+00:00
5	5	pending	45.75	2	2024-03-08 17:20:00	\N	Leave at the door; ring twice	2024-03-08 17:20:00+00:00
6	6	shipped	310.40	5	2024-03-10 13:00:00	2024-03-11 09:00:00	Fragile: "glass"	2024-03-11 09:00:00+00:00
7	8	paid	76.20	2	2024-03-11 18:45:00	\N	\N	2024-03-11 18:46:00+00:00
8	2		19.99	1	2024-03-12 08:00:00	\N	Status lost in an old import	2024-03-12 08:00:00+00:00
9	3	shipped	64.00	2	2024-03-14 15:30:00	\N	Shipping date never recorded	2024-03-15 10:00:00+00:00
10	7	paid	1499.00	1	2024-03-15 21:05:00	\N	C:\\Users\\ravi\\invoice.pdf	2024-03-15 21:05:00+00:00
\.


-- Keys, indexes and constraints, after the rows so each builds once.
CREATE UNIQUE INDEX customers_pkey ON customers (id);
CREATE UNIQUE INDEX customers_uq_email ON customers (email);
CREATE UNIQUE INDEX orders_pkey ON orders (id);
CREATE INDEX orders_idx_customer ON orders (customer_id);
CREATE INDEX orders_idx_status_date ON orders (status, ordered_at);
ALTER TABLE customers ADD CONSTRAINT customers_pkey PRIMARY KEY USING INDEX customers_pkey;
ALTER TABLE customers ADD CONSTRAINT customers_uq_email UNIQUE USING INDEX customers_uq_email;
ALTER TABLE orders ADD CONSTRAINT orders_pkey PRIMARY KEY USING INDEX orders_pkey;
ALTER TABLE orders ADD CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers (id) NOT VALID;
DO $f$ BEGIN
    ALTER TABLE orders VALIDATE CONSTRAINT fk_orders_customer;
EXCEPTION WHEN foreign_key_violation THEN
    RAISE WARNING 'foreign key % has rows without a parent: it stays NOT VALID, and new rows are checked', 'fk_orders_customer';
END $f$;
SELECT setval(pg_get_serial_sequence('customers', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM customers)::numeric, 0) + 1, 1001), 9223372036854775807)::bigint, false);
COMMENT ON TABLE customers IS 'People who bought at least once';
SELECT setval(pg_get_serial_sequence('orders', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM orders)::numeric, 0) + 1, 5001), 9223372036854775807)::bigint, false);
CREATE FUNCTION orders_updated_at_on_update() RETURNS trigger LANGUAGE plpgsql AS $f$
BEGIN
    IF NEW IS DISTINCT FROM OLD AND NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at THEN
        NEW.updated_at := CURRENT_TIMESTAMP;
    END IF;
    RETURN NEW;
END
$f$;
CREATE TRIGGER orders_updated_at_on_update BEFORE UPDATE ON orders FOR EACH ROW EXECUTE FUNCTION orders_updated_at_on_update();

수정 사항

  1. customers의 "id" 열은 부호가 없어서, 음수가 아닌지 확인하는 체크 제약과 함께 bigint(으)로 만들었어요.
  2. customers의 "signed_up" 열은 이제 NULL을 허용해요. 일부 값을 저장할 수 없어 NULL이 됐어요.
  3. customers의 "signed_up" 열 기본값 0000‑00‑00은(는) PostgreSQL이 받는 날짜가 아니라서 기본값을 없앴어요.
  4. orders의 "customer_id" 열은 부호가 없어서, 음수가 아닌지 확인하는 체크 제약과 함께 bigint(으)로 만들었어요.
  5. orders의 "id" 열은 부호가 없어서, 음수가 아닌지 확인하는 체크 제약과 함께 bigint(으)로 만들었어요.
  6. orders의 "items" 열은 부호가 없어서, 음수가 아닌지 확인하는 체크 제약과 함께 integer(으)로 만들었어요.
  7. orders의 "status" 열에서 1개 행에 MySQL이 잘못된 입력에 저장하는 빈 값이 있어요. 값 체크 제약이 이 값을 허용해요.
  8. orders의 "updated_at" 열은 업데이트할 때마다 현재 시간으로 바뀌어요. PostgreSQL에서는 트리거가 이를 처리해요.

확인 필요

  • customers의 "signed_up" 열에 있는 1개 값은 0000‑00‑00 같은 0 날짜나 불가능한 날짜예요. PostgreSQL이 저장할 수 없어 NULL로 두었어요. 이 날짜에 의미가 있다면 덤프하기 전에 원본에서 실제 날짜로 바꾸세요.
  • orders의 "shipped_at" 열에 있는 1개 값은 0000‑00‑00 00:00:00 같은 0 날짜나 불가능한 날짜예요. PostgreSQL이 저장할 수 없어 NULL로 두었어요. 이 날짜에 의미가 있다면 덤프하기 전에 원본에서 실제 날짜로 바꾸세요.

파일은 이 컴퓨터에서 변환되고 업로드되지 않아요.

다른 샘플:

모든 데이터베이스 조합

행은 덤프의 원본, 열은 스크립트의 대상 데이터베이스예요. 조합마다 설정된 변환기, 적용 규칙, 스크립트 불러오는 법을 담은 페이지가 있어요.

모든 조합의 데이터 타입

유지되는 것과 보고되는 것

변환기는 데이터베이스 서버 없이 덤프를 직접 읽고 그 내용으로 스크립트를 써요. 조합 페이지마다 적용 규칙(25~67개)과 각 규칙이 보고서에 쓰는 줄이 나와요.

스크립트에 유지

  • 테이블과 열, 각각 대상의 가장 가까운 타입과 길이, 정밀도로.
  • 기본 키, 고유 키, 외래 키, 인덱스, 기본값.
  • AUTO_INCREMENT, IDENTITY, serial 열. 행 ID를 유지하고 카운터는 덤프가 멈춘 곳부터 이어져요.
  • 모든 행. 날짜, 소수, 텍스트, 바이너리 값은 덤프 그대로예요.

보고서에 기록

  • 대상이 그대로 담을 수 없는 값(PostgreSQL의 0000-00-00 날짜 등)과 열, 개수.invalid_date_null
  • 대상에 없는 타입(ENUM, INET6 등)과 각각 바뀐 타입.type_replaced
  • 뷰, 트리거, 프로시저, 함수, 이벤트를 이름으로. DB마다 자체 언어라 변환하지 않아요.not_converted_objects
  • 문자 집합에서 유효하지 않은 텍스트와 이미 4바이트 문자를 잃은 덤프.invalid_utf8_replaced

pgloader와 비교한 측정 결과

같은 덤프를 2026년 10월에 한 컴퓨터(SATA SSD를 단 10코어 i9-10900K)에서 IntoSQL과 pgloader 3.6.7로 변환하고 불러왔어요.

  • 2, -1, -5를 담은 TINYINT(1) 열: pgloader는 경고 없이 모두 true로 불러와요. IntoSQL은 숫자를 유지하고 보고서에 이유가 나와요.
  • 기본값이 'it's'인 열, 백틱이 들어간 이름의 테이블, 빈 값을 담은 ENUM, 24시간이 넘는 TIME이 있는 덤프: pgloader는 멈춰요. IntoSQL은 변환하고 불러와요.
  • pgloader로 불러온 결과에는 기본 키, 고유 키, 외래 키와 IDENTITY가 사라져요. IntoSQL은 모두 유지해요.
  • 3,000만 행이 담긴 5.3 GB 덤프: pgloader는 먼저 실행 중인 MySQL에 복원해야 해서 18분이 걸리고, 그 뒤 기본 설정으로는 메모리가 부족해져요. IntoSQL은 덤프를 10초 만에 변환하고, psql은 약 3분 만에 스크립트를 불러와요.
  • MySQL 5.5부터 9까지, MariaDB 10.3부터 12까지의 덤프 476개를 PostgreSQL 13과 18에 불러온 결과: 불러오기 오류는 없었고, 보고서에 기록 없이 바뀐 값도 없었어요.
MySQL에서 PostgreSQL로 페이지

지금 쓰는 데이터베이스 내보내기

변환기는 실행 중인 서버가 아니라 파일을 읽어요. 각 데이터베이스는 자체 도구로 파일을 써요.

데이터베이스 마이그레이션 질문

여기에 답이 없나요? 문의 페이지로 연락하시면 담당자가 답장해요. 문의 페이지

덤프가 업로드되나요?

아니요. 변환기는 브라우저에서 실행되고 디스크의 덤프를 조각조각 읽으므로, 덤프가 컴퓨터 밖으로 나가지 않아요. 데스크톱 앱과 명령줄도 컴퓨터에서 변환해요.

덤프는 얼마나 커도 되나요?

변환기는 덤프 전체를 메모리에 올리지 않아요. 파일을 범위별로 두 번 읽고, 읽는 대로 스크립트를 써요. 수 GB 덤프도 브라우저, 데스크톱 앱, 명령줄에서 변환돼요.

어떤 버전의 덤프를 쓸 수 있나요?

MySQL 5.5~9, MariaDB 10.3~12, PostgreSQL 10 이상, SQL Server 2017 이상, SQLite 3.0 이상, Oracle 11g 이상이에요. 스크립트가 불러와지는 버전은 각 조합 페이지에 나와요.

실행 중인 데이터베이스 서버가 필요한가요?

아니요. 변환기가 덤프 파일을 직접 읽으므로 원본 데이터베이스는 실행될 필요가 없어요. 스크립트는 psql, mysql, sqlcmd 같은 대상의 클라이언트로 불러와요.

변환되지 않는 것은요?

뷰, 트리거, 저장 프로시저, 함수, 이벤트는 DB마다 자체 언어로 작성되어 보고서에 이름으로 나와요. 테이블, 키, 인덱스, 행은 모두 스크립트에 있어요.

스크립트를 데이터베이스에 바로 불러올 수 있나요?

데스크톱 앱과 intosql load 명령은 SQLite에 무료로, PostgreSQL, MySQL, MariaDB에는 IntoSQL Pro로 바로 써요. SQL Server와 Oracle은 sqlcmd나 sqlplus로 실행하세요.