데이터베이스를 다른 데이터베이스로 변환
mysqldump, mariadb-dump, pg_dump, SSMS, SQL Developer, SQLcl 덤프나 SQLite .db 파일을 놓으면, 같은 테이블, 키, 인덱스, 데이터를 담은 PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle 스크립트를 받아요. 모든 변경은 보고서에 나오고, 덤프는 컴퓨터 밖으로 나가지 않아요.
18개 행 변환, 수정 8개, 거부 없음
shop_2024.sql의 테이블MySQL 8.0.46 덤프 · mysqldump(으)로 작성됨 · utf8mb4
customers8개 행3
7개 열 id bigint not null name varchar(100) not null email varchar(150) not null country varchar(2) not null is_active boolean not null signed_up date created_at timestamptz(0) not null orders10개 행5
9개 열 id bigint not null customer_id bigint not null status text not null total numeric(10,2) not null items integer not null ordered_at timestamp(0) not null shipped_at timestamp(0) note varchar(255) updated_at timestamptz(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();
수정 사항
- customers의 "id" 열은 부호가 없어서, 음수가 아닌지 확인하는 체크 제약과 함께 bigint(으)로 만들었어요.
- customers의 "signed_up" 열은 이제 NULL을 허용해요. 일부 값을 저장할 수 없어 NULL이 됐어요.
- customers의 "signed_up" 열 기본값 0000‑00‑00은(는) PostgreSQL이 받는 날짜가 아니라서 기본값을 없앴어요.
- orders의 "customer_id" 열은 부호가 없어서, 음수가 아닌지 확인하는 체크 제약과 함께 bigint(으)로 만들었어요.
- orders의 "id" 열은 부호가 없어서, 음수가 아닌지 확인하는 체크 제약과 함께 bigint(으)로 만들었어요.
- orders의 "items" 열은 부호가 없어서, 음수가 아닌지 확인하는 체크 제약과 함께 integer(으)로 만들었어요.
- orders의 "status" 열에서 1개 행에 MySQL이 잘못된 입력에 저장하는 빈 값이 있어요. 값 체크 제약이 이 값을 허용해요.
- 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로 두었어요. 이 날짜에 의미가 있다면 덤프하기 전에 원본에서 실제 날짜로 바꾸세요.
파일은 이 컴퓨터에서 변환되고 업로드되지 않아요.
다른 샘플:
모든 데이터베이스 조합
행은 덤프의 원본, 열은 스크립트의 대상 데이터베이스예요. 조합마다 설정된 변환기, 적용 규칙, 스크립트 불러오는 법을 담은 페이지가 있어요.
- MySQL
- MariaDB
- PostgreSQL
- SQL Server
- SQLite
- Oracle
유지되는 것과 보고되는 것
변환기는 데이터베이스 서버 없이 덤프를 직접 읽고 그 내용으로 스크립트를 써요. 조합 페이지마다 적용 규칙(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
mysqldump, mysqlpump, phpMyAdmin, Adminer 덤프(.sql 또는 .sql.gz). --default-character-set=utf8mb4 --hex-blob --routines --triggers --events로 가장 많이 유지돼요.
MySQL에서 PostgreSQL로 마이그레이션 가이드MariaDB
mariadb-dump, mysqldump, phpMyAdmin, Adminer 덤프(.sql 또는 .sql.gz), MySQL과 같은 옵션으로.
MariaDB에서 PostgreSQL로 마이그레이션 가이드PostgreSQL
pg_dump나 pg_dumpall의 일반 덤프. 사용자 지정 아카이브(-Fc)는 서버 없이 pg_restore -f dump.sql로 바꿀 수 있어요.
PostgreSQL에서 MySQL로 마이그레이션 가이드SQL Server
SSMS 스크립트 생성에서 스크립팅할 데이터 형식을 스키마 및 데이터로 정해 쓴 스크립트. dbatools와 mssql-scripter도 같아요.
SQL Server에서 PostgreSQL로 마이그레이션 가이드SQLite
데이터베이스 파일 자체(.db, .sqlite, .sqlite3) 또는 sqlite3 app.db .dump가 쓰는 SQL.
SQLite에서 PostgreSQL로 마이그레이션 가이드Oracle
SQL Developer 데이터베이스 내보내기나 SQLcl이 쓰는 DDL과 Insert 문이 담긴 .sql 파일. exp나 expdp의 .dmp 파일은 먼저 가져온 뒤 다시 내보내야 해요.
Oracle에서 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로 실행하세요.