PostgreSQL에서 MySQL로 변환
pg_dump나 pg_dumpall로 만든 .sql 또는 .sql.gz 일반 덤프를 놓으면, 같은 테이블, 키, 인덱스, 데이터를 담은 MySQL 스크립트를 다운로드할 수 있어요. MySQL이(가) 그대로 담을 수 없는 값과 옮기지 않는 객체는 모두 보고서에 나와요.
18개 행 변환, 수정 3개, 거부 없음
shop_2024_postgres.sql의 테이블PostgreSQL 18.6 덤프 · pg_dump(으)로 작성됨 · utf8mb4
customers8개 행2
8개 열 id int not null name text not null email varchar(768) not null country char(2) not null is_active tinyint(1) not null tags json not null signed_up date created_at datetime(6) not null orders10개 행1
10개 열 id int not null customer_id int not null status enum('pending','paid','shipped','cancelled') not null total decimal(10,2) not null items smallint not null ordered_at datetime(6) not null shipped_at datetime(6) note text details json delivery varchar(100)
변환되지 않음
- 뷰 paid_orders
데이터베이스마다 이 객체를 자체 언어로 작성해요. MySQL에 맞게 다시 작성하세요.
-- Written by IntoSQL from a PostgreSQL dump. Load it with: mysql --default-character-set=utf8mb4 <database> < <file>
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
SET UNIQUE_CHECKS = 0;
SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO,ALLOW_INVALID_DATES';
CREATE TABLE `customers` (
`id` int NOT NULL AUTO_INCREMENT,
`name` text NOT NULL,
`email` varchar(768) NOT NULL,
`country` char(2) NOT NULL DEFAULT 'US',
`is_active` tinyint(1) NOT NULL DEFAULT 1,
`tags` json NOT NULL,
`signed_up` date,
`created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
UNIQUE KEY `customers_email_key` (`email`),
PRIMARY KEY (`id`)
) AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='People who bought at least once';
CREATE TABLE `orders` (
`id` int NOT NULL AUTO_INCREMENT,
`customer_id` int NOT NULL,
`status` enum('pending','paid','shipped','cancelled') NOT NULL DEFAULT 'pending',
`total` decimal(10,2) NOT NULL,
`items` smallint NOT NULL DEFAULT 1,
`ordered_at` datetime(6) NOT NULL,
`shipped_at` datetime(6),
`note` text,
`details` json,
`delivery` varchar(100),
PRIMARY KEY (`id`),
KEY `idx_orders_customer` (`customer_id`),
KEY `idx_orders_status_date` (`status`,`ordered_at`),
CONSTRAINT `orders_total_check` CHECK (`total` >= (0)),
CONSTRAINT `orders_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`)
) AUTO_INCREMENT=5001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
INSERT INTO `customers` (`id`,`name`,`email`,`country`,`is_active`,`tags`,`signed_up`,`created_at`) VALUES (1,'Ana Martínez','ana@example.com','MX',1,'["vip"]','2023-01-15','2023-01-15 10:24:00'),(2,'Zoë Müller','zoe@example.de','DE',1,'[]','2023-02-03','2023-02-03 08:11:42'),(3,'José Peña','jose@example.es','ES',0,'["wholesale","late payer"]','2023-03-21','2023-03-21 19:05:17'),(4,'李雷','lilei@example.cn','CN',1,'[]','2023-05-09','2023-05-09 02:40:00'),(5,'Noah O\'Brien','noah@example.ie','IE',1,'[]',NULL,'2023-06-30 14:00:00'),(6,'Amélie Laurent','amelie@example.fr','FR',1,'["vip"]','2024-01-02','2024-01-02 09:30:00'),(7,'Ravi Patel','ravi@example.in','IN',0,'[]','2024-02-29','2024-02-29 23:59:59'),(8,'Sofia Rossi 🌻','sofia@example.it','IT',1,'[]','2024-04-12','2024-04-12 12:12:12');
INSERT INTO `orders` (`id`,`customer_id`,`status`,`total`,`items`,`ordered_at`,`shipped_at`,`note`,`details`,`delivery`) VALUES (1,1,'shipped',129.90,3,'2024-03-01 10:00:00','2024-03-02 16:30:00',NULL,'{"gift": false}','1 day 06:30:00'),(2,2,'paid',54.00,1,'2024-03-02 11:15:00',NULL,'Gift wrap 🎁','{"gift": true, "wrap": "red"}',NULL),(3,1,'cancelled',12.50,1,'2024-03-03 09:45:00',NULL,'Customer changed their mind',NULL,NULL),(4,4,'shipped',980.00,12,'2024-03-05 02:10:00','2024-03-07 08:00:00','请小心轻放','{"fragile": true}','2 days 05:50:00'),(5,5,'pending',45.75,2,'2024-03-08 17:20:00',NULL,'Leave at the door; ring twice',NULL,NULL),(6,6,'shipped',310.40,5,'2024-03-10 13:00:00','2024-03-11 09:00:00','Fragile: "glass"','{"fragile": true}','20:00:00'),(7,8,'paid',76.20,2,'2024-03-11 18:45:00',NULL,NULL,NULL,NULL),(8,2,'shipped',19.99,1,'2024-03-12 08:00:00',NULL,'Shipped date set to infinity by an old import',NULL,NULL),(9,3,'shipped',64.00,2,'2024-03-14 15:30:00','2024-03-15 10:00:00','Two parcels','{"parcels": [1, 2]}','18:30:00'),(10,7,'paid',1499.00,1,'2024-03-15 21:05:00',NULL,'C:\\Users\\ravi\\invoice.pdf',NULL,NULL);
SET UNIQUE_CHECKS = 1;
SET FOREIGN_KEY_CHECKS = 1;
수정 사항
- customers의 "created_at" 열에는 시간대가 있는 시점이 들어 있어요. MySQL에는 시간대를 유지하는 타입이 없어서 datetime(6)(으)로 UTC로 저장해요.
- customers의 "tags" 열은 MySQL에 없는 text[](이)라서 같은 값을 담은 json(으)로 만들었어요.
- orders의 "delivery" 열은 MySQL에 없는 interval(이)라서 같은 값을 담은 varchar(100)(으)로 만들었어요.
확인 필요
- 뷰, 트리거, 루틴, 이벤트 1개가 변환되지 않았어요. 보고서에 각각 나와 있어요. MySQL에서 직접 다시 만드세요.
- customers의 "tags" 열 기본값을 MySQL용으로 쓸 수 없어(a value its type can't hold) 기본값 없이 만들었어요. 새 행에 필요하면 기본값을 직접 추가하세요.
- orders의 인덱스 idx_orders_details은(는) MySQL용으로 쓸 수 없는 식을 사용해서(neither MySQL 5.7 nor MariaDB index an expression) 만들지 않았어요. 쿼리에 필요하면 인덱스를 직접 만드세요.
- orders의 "shipped_at" 열에 있는 1개 값은 infinity처럼 MySQL이(가) 저장할 수 없는 날짜라서 NULL로 두었어요. MySQL은(는) 1년부터 9999년까지만 저장하고 infinity는 없어요. 이 날짜가 중요하면 원본에서 바꾸세요.
파일은 이 컴퓨터에서 변환되고 업로드되지 않아요.
다른 샘플:
PostgreSQL에서 MySQL로 바뀌는 점
각 행은 변환기가 적용하는 규칙이며, 규칙이 데이터를 바꿀 때 보고서에 쓰는 줄이 함께 나와요.
boolean
tinyint(1)
MySQL의 BOOLEAN은 TINYINT(1)이에요. true는 1, false는 0이에요.
varchar(n), char(n), text
1024자까지는 varchar(n), 255자까지는 char(n), 그 이상은 text
텍스트는 utf8mb4로 모든 문자를 유지해요. 키에 있는 열은 키가 담을 수 있는 최대 길이인 varchar(768)까지예요. 기본값이 있는 텍스트도 마찬가지인데, MySQL 5.7은 varchar에만 기본값을 줄 수 있기 때문이에요.
numeric(p,s) past 65 digits or 30 decimals, and numeric values past what decimal(65,30) holds
varchar
MySQL의 decimal은 소수 30자리를 포함해 65자리까지 담아요. 더 넓은 숫자는 모든 자릿수가 정확하도록 텍스트로 유지하고, 정밀도가 없는 numeric은 값이 들어가면 decimal(65,30)이 돼요.
보고서 줄: decimal_as_text
money
decimal(19,2)
MySQL에는 money 타입이 없어요. 금액은 서버 로캘이 붙인 통화 기호 없이 숫자로 유지해요.
보고서 줄: type_replaced
interval
PostgreSQL의 텍스트를 담은 varchar(100)
MySQL의 TIME은 838시간까지의 기간을 담지만 interval에는 월과 일이 있어요. 텍스트가 모든 부분을 유지해요.
보고서 줄: type_replaced
arrays (integer[], text[]...)
json 배열
MySQL에는 배열이 없어요. JSON 배열은 모든 항목과 NULL을 유지하고 JSON 함수로 읽을 수 있어요.
보고서 줄: type_replaced
ranges, geometric types, tsvector, xml, hstore, composite and extension types
PostgreSQL의 텍스트를 담은 longtext
MySQL에는 같은 타입이 없어서 각 값은 PostgreSQL이 쓴 텍스트를 유지해요.
보고서 줄: type_replaced
json, jsonb
json
같은 JSON 값이에요. jsonb의 키 순서와 공백은 서버가 정한 대로예요.
timestamp
datetime(p)
timestamp without time zone은 datetime처럼 시계에 표시된 시각이에요.
timestamp with time zone
UTC 기준 datetime(p)
MySQL의 TIMESTAMP는 2038년까지만 담아서 시점을 UTC 기준 datetime으로 저장해요. 덤프에 적힌 오프셋과 상관없이 같은 시점이에요.
보고서 줄: moments_as_utc
time
time(p)
MySQL의 TIME은 24:00:00을 포함해 하루의 모든 시각을 담아요.
infinity, -infinity, BC dates and years past 9999
NULL
MySQL은 1000년부터 9999년까지만 저장하고 infinity는 없어요. 이 값은 NULL이 되고 보고서에 개수가 나와요.
보고서 줄: date_out_of_range
NaN and Infinity in numeric, real and double precision
NULL
MySQL의 숫자에는 NaN이나 Infinity가 없어서 이 값은 NULL이 되고 보고서에 개수가 나와요.
보고서 줄: invalid_value_null
NOT NULL columns with values that become NULL
NOT NULL 제거
값을 NULL로 바꿔야 했던 열은 NOT NULL을 유지할 수 없어요. 유지하면 불러오기가 멈춰요.
보고서 줄: not_null_relaxed
enum types
같은 레이블의 enum(...)
MySQL의 ENUM은 레이블을 같은 순서로 유지해요.
uuid, inet, cidr
uuid는 char(36), inet과 cidr은 varchar(43)
MySQL에는 uuid나 주소 타입이 없어요. 텍스트가 모든 값을 유지해요.
bytea
blob, mediumblob 또는 longblob, 키에서는 varbinary(3072)
바이트는 바이트 그대로 남아요.
bit(n)
64까지는 bit(n), 그 이상은 텍스트
64비트까지의 비트 문자열은 비트가 만드는 숫자가 되고, 더 긴 것은 자릿수를 그대로 유지해요.
citext and nondeterministic collations
정확한 비교
테이블은 utf8mb4_bin을 써서 PostgreSQL처럼 텍스트를 정확히 비교해요. 원본에서 대소문자를 무시하던 열은 그 동작을 잃어요.
보고서 줄: case_insensitive_collation
serial, identity
AUTO_INCREMENT, 가장 큰 id 다음부터 이어짐
기본 키의 첫 열이 번호를 매기고, 카운터는 시퀀스가 있던 곳부터 이어져요.
a second serial or identity column in a table
일반 정수
MySQL은 테이블마다 한 열만 번호를 매겨요. 다른 열은 카운터 없이 값을 유지해요.
보고서 줄: counter_dropped
sequences not owned by a column
만들지 않음
MySQL에는 시퀀스가 없어요. 시퀀스로 번호를 매기던 열은 대신 AUTO_INCREMENT가 돼요.
보고서 줄: sequence_not_converted
generated columns
원본처럼 STORED인 생성 열
MySQL도 같은 방식으로 계산해요.
generated columns with functions MySQL lacks
일반 열
MySQL용으로 쓸 수 없는 수식은 일반 열로 남고 보고서에 한 줄 기록돼요.
보고서 줄: generated_not_translated
defaults with functions MySQL lacks, and defaults from a sequence
기본값 없음
MySQL용으로 쓸 수 없는 기본값은 제외하고 보고해요.
보고서 줄: default_not_translated
CHECK constraints
변환해서 CREATE TABLE 안에 인라인으로
MySQL 8.0.16과 MariaDB는 체크 제약을 적용하고, MySQL 5.7은 검사하지 않고 보관해요.
CHECK constraints with functions MySQL lacks
만들지 않음
MySQL용으로 쓸 수 없는 체크 제약은 제외하고 보고해요.
보고서 줄: check_skipped
CHECK ... NOT VALID
만들지 않음
PostgreSQL은 기존 행을 검사한 적이 없어서 그 행이 제약을 어길 수 있어요.
보고서 줄: check_not_valid
gin, gist, brin and hash indexes, partial and expression indexes
만들지 않음
MySQL에는 열 전체에 대한, WHERE 없는 b-tree, 전문, 공간 인덱스만 있어요.
보고서 줄: index_skipped
foreign keys
외래 키, FOREIGN_KEY_CHECKS=0으로 불러옴
행은 어떤 순서로든 불러오고, 이후 키가 새 행을 검사해요.
foreign keys to tables the dump doesn't create
만들지 않음
키는 없는 테이블을 가리킬 수 없어요.
보고서 줄: foreign_key_skipped
partitioned tables
모든 파티션의 행을 담은 하나의 테이블
행은 같아요. 필요하면 MySQL에서 테이블을 다시 파티션으로 나누세요.
보고서 줄: partitions_dropped
schemas
하나의 데이터베이스, 테이블 이름 앞에 스키마 이름
MySQL의 스키마는 데이터베이스이고, 한 데이터베이스에 불러오는 스크립트는 이를 만들 수 없어요. public의 테이블은 이름을 유지해요.
보고서 줄: schemas_merged
views, functions, procedures, triggers, rules, policies, extensions and types
보고서에 나열
코드가 PostgreSQL의 언어로 작성되어 있어서 직접 다시 만들 수 있도록 나열해요.
보고서 줄: not_converted_objects
dumps without CREATE TABLE (--data-only)
값으로 판단한 타입
데이터만 있는 덤프에는 행만 있어서 타입을 값으로 판단해요.
보고서 줄: no_schema
expressions in INSERT values
NULL
데이터베이스를 실행하지 않는 변환기는 이 식을 계산할 수 없어요.
보고서 줄: expression_value
types IntoSQL doesn't know
longtext
텍스트는 어떤 값이든 담아요. 불러온 뒤 타입을 바꾸세요.
보고서 줄: unknown_type
text that isn't valid in its encoding
잘못된 바이트를 대체 문자로
텍스트는 올바른 utf8mb4여야 해요.
보고서 줄: invalid_utf8_replaced
text decoded twice (ñ)
그대로 복사
덤프에 정확히 이 문자들이 있으므로 그대로 복사하고, 보고서에서 알려 줘요.
보고서 줄: mojibake_suspected
| PostgreSQL에서 | MySQL에서 | 보고서 줄 |
|---|---|---|
| boolean | tinyint(1)MySQL의 BOOLEAN은 TINYINT(1)이에요. true는 1, false는 0이에요. | |
| varchar(n), char(n), text | 1024자까지는 varchar(n), 255자까지는 char(n), 그 이상은 text텍스트는 utf8mb4로 모든 문자를 유지해요. 키에 있는 열은 키가 담을 수 있는 최대 길이인 varchar(768)까지예요. 기본값이 있는 텍스트도 마찬가지인데, MySQL 5.7은 varchar에만 기본값을 줄 수 있기 때문이에요. | |
| numeric(p,s) past 65 digits or 30 decimals, and numeric values past what decimal(65,30) holds | varcharMySQL의 decimal은 소수 30자리를 포함해 65자리까지 담아요. 더 넓은 숫자는 모든 자릿수가 정확하도록 텍스트로 유지하고, 정밀도가 없는 numeric은 값이 들어가면 decimal(65,30)이 돼요. | decimal_as_text |
| money | decimal(19,2)MySQL에는 money 타입이 없어요. 금액은 서버 로캘이 붙인 통화 기호 없이 숫자로 유지해요. | type_replaced |
| interval | PostgreSQL의 텍스트를 담은 varchar(100)MySQL의 TIME은 838시간까지의 기간을 담지만 interval에는 월과 일이 있어요. 텍스트가 모든 부분을 유지해요. | type_replaced |
| arrays (integer[], text[]...) | json 배열MySQL에는 배열이 없어요. JSON 배열은 모든 항목과 NULL을 유지하고 JSON 함수로 읽을 수 있어요. | type_replaced |
| ranges, geometric types, tsvector, xml, hstore, composite and extension types | PostgreSQL의 텍스트를 담은 longtextMySQL에는 같은 타입이 없어서 각 값은 PostgreSQL이 쓴 텍스트를 유지해요. | type_replaced |
| json, jsonb | json같은 JSON 값이에요. jsonb의 키 순서와 공백은 서버가 정한 대로예요. | |
| timestamp | datetime(p)timestamp without time zone은 datetime처럼 시계에 표시된 시각이에요. | |
| timestamp with time zone | UTC 기준 datetime(p)MySQL의 TIMESTAMP는 2038년까지만 담아서 시점을 UTC 기준 datetime으로 저장해요. 덤프에 적힌 오프셋과 상관없이 같은 시점이에요. | moments_as_utc |
| time | time(p)MySQL의 TIME은 24:00:00을 포함해 하루의 모든 시각을 담아요. | |
| infinity, -infinity, BC dates and years past 9999 | NULLMySQL은 1000년부터 9999년까지만 저장하고 infinity는 없어요. 이 값은 NULL이 되고 보고서에 개수가 나와요. | date_out_of_range |
| NaN and Infinity in numeric, real and double precision | NULLMySQL의 숫자에는 NaN이나 Infinity가 없어서 이 값은 NULL이 되고 보고서에 개수가 나와요. | invalid_value_null |
| NOT NULL columns with values that become NULL | NOT NULL 제거값을 NULL로 바꿔야 했던 열은 NOT NULL을 유지할 수 없어요. 유지하면 불러오기가 멈춰요. | not_null_relaxed |
| enum types | 같은 레이블의 enum(...)MySQL의 ENUM은 레이블을 같은 순서로 유지해요. | |
| uuid, inet, cidr | uuid는 char(36), inet과 cidr은 varchar(43)MySQL에는 uuid나 주소 타입이 없어요. 텍스트가 모든 값을 유지해요. | |
| bytea | blob, mediumblob 또는 longblob, 키에서는 varbinary(3072)바이트는 바이트 그대로 남아요. | |
| bit(n) | 64까지는 bit(n), 그 이상은 텍스트64비트까지의 비트 문자열은 비트가 만드는 숫자가 되고, 더 긴 것은 자릿수를 그대로 유지해요. | |
| citext and nondeterministic collations | 정확한 비교테이블은 utf8mb4_bin을 써서 PostgreSQL처럼 텍스트를 정확히 비교해요. 원본에서 대소문자를 무시하던 열은 그 동작을 잃어요. | case_insensitive_collation |
| serial, identity | AUTO_INCREMENT, 가장 큰 id 다음부터 이어짐기본 키의 첫 열이 번호를 매기고, 카운터는 시퀀스가 있던 곳부터 이어져요. | |
| a second serial or identity column in a table | 일반 정수MySQL은 테이블마다 한 열만 번호를 매겨요. 다른 열은 카운터 없이 값을 유지해요. | counter_dropped |
| sequences not owned by a column | 만들지 않음MySQL에는 시퀀스가 없어요. 시퀀스로 번호를 매기던 열은 대신 AUTO_INCREMENT가 돼요. | sequence_not_converted |
| generated columns | 원본처럼 STORED인 생성 열MySQL도 같은 방식으로 계산해요. | |
| generated columns with functions MySQL lacks | 일반 열MySQL용으로 쓸 수 없는 수식은 일반 열로 남고 보고서에 한 줄 기록돼요. | generated_not_translated |
| defaults with functions MySQL lacks, and defaults from a sequence | 기본값 없음MySQL용으로 쓸 수 없는 기본값은 제외하고 보고해요. | default_not_translated |
| CHECK constraints | 변환해서 CREATE TABLE 안에 인라인으로MySQL 8.0.16과 MariaDB는 체크 제약을 적용하고, MySQL 5.7은 검사하지 않고 보관해요. | |
| CHECK constraints with functions MySQL lacks | 만들지 않음MySQL용으로 쓸 수 없는 체크 제약은 제외하고 보고해요. | check_skipped |
| CHECK ... NOT VALID | 만들지 않음PostgreSQL은 기존 행을 검사한 적이 없어서 그 행이 제약을 어길 수 있어요. | check_not_valid |
| gin, gist, brin and hash indexes, partial and expression indexes | 만들지 않음MySQL에는 열 전체에 대한, WHERE 없는 b-tree, 전문, 공간 인덱스만 있어요. | index_skipped |
| foreign keys | 외래 키, FOREIGN_KEY_CHECKS=0으로 불러옴행은 어떤 순서로든 불러오고, 이후 키가 새 행을 검사해요. | |
| foreign keys to tables the dump doesn't create | 만들지 않음키는 없는 테이블을 가리킬 수 없어요. | foreign_key_skipped |
| partitioned tables | 모든 파티션의 행을 담은 하나의 테이블행은 같아요. 필요하면 MySQL에서 테이블을 다시 파티션으로 나누세요. | partitions_dropped |
| schemas | 하나의 데이터베이스, 테이블 이름 앞에 스키마 이름MySQL의 스키마는 데이터베이스이고, 한 데이터베이스에 불러오는 스크립트는 이를 만들 수 없어요. public의 테이블은 이름을 유지해요. | schemas_merged |
| views, functions, procedures, triggers, rules, policies, extensions and types | 보고서에 나열코드가 PostgreSQL의 언어로 작성되어 있어서 직접 다시 만들 수 있도록 나열해요. | not_converted_objects |
| dumps without CREATE TABLE (--data-only) | 값으로 판단한 타입데이터만 있는 덤프에는 행만 있어서 타입을 값으로 판단해요. | no_schema |
| expressions in INSERT values | NULL데이터베이스를 실행하지 않는 변환기는 이 식을 계산할 수 없어요. | expression_value |
| types IntoSQL doesn't know | longtext텍스트는 어떤 값이든 담아요. 불러온 뒤 타입을 바꾸세요. | unknown_type |
| text that isn't valid in its encoding | 잘못된 바이트를 대체 문자로텍스트는 올바른 utf8mb4여야 해요. | invalid_utf8_replaced |
| text decoded twice (ñ) | 그대로 복사덤프에 정확히 이 문자들이 있으므로 그대로 복사하고, 보고서에서 알려 줘요. | mojibake_suspected |
스크립트를 MySQL에 불러오기
스크립트는 테이블을 만들고 행을 복사한 다음 키, 인덱스, 외래 키를 추가해요. 그래서 빨리 불러오고 첫 오류에서 멈춰요.
mysql --default-character-set=utf8mb4 mydb < postgresql.mysql.sql외래 키는 덤프에 선언된 대로 만들고, 행을 불러오는 동안 FOREIGN_KEY_CHECKS=0을 써요. 그래서 존재하지 않는 행을 가리키는 행이 있어도 불러오기가 멈추지 않아요.
큰 덤프는 서버와 같은 컴퓨터에서 클라이언트를 실행하고, 한 행이 아주 크면 max_allowed_packet을 늘리세요.
IntoSQL Pro는 데스크톱 앱이나 명령줄에서 파일을 MySQL에 바로 불러와요. 스크립트를 따로 만들 필요가 없어요.
좋은 결과를 위한 PostgreSQL 덤프 방법
변환기는 덤프에 담긴 내용을 읽어요. 다음 옵션을 쓰면 더 많은 데이터가 덤프에 남아요:
- pg_dump의 기본값인 --format=plain은 SQL을 써요. custom 또는 directory 아카이브(-Fc, -Fd)는 데이터베이스 서버 없이 pg_restore -f dump.sql로 SQL이 돼요.
- --no-owner --no-privileges는 어차피 변환기가 건너뛰는 역할과 권한을 빼서 덤프가 작아져요.
- pg_dumpall은 모든 데이터베이스를 한 파일에 덤프해요. 각 데이터베이스의 테이블 이름에 그 데이터베이스 이름이 붙어서 충돌하지 않아요.
변환되지 않는 것
뷰, 구체화된 뷰, 함수, 프로시저, 트리거, 규칙, 행 보안 정책, 확장, 타입은 PostgreSQL의 자체 언어로 작성돼요. 보고서에 이름으로 나열되고 몰래 빠지는 일은 없으므로, MySQL에 맞게 다시 작성할 수 있어요.
PostgreSQL에서 MySQL로 변환에 관한 질문
여기에 답이 없나요? 문의 페이지로 연락하시면 담당자가 답장해요. 문의 페이지
덤프가 업로드되나요?
아니요. 변환기는 브라우저에서 실행되고 디스크의 덤프를 조각조각 읽으므로, 덤프가 컴퓨터 밖으로 나가지 않아요. 데스크톱 앱과 명령줄도 컴퓨터에서 변환해요.
덤프는 얼마나 커도 되나요?
변환기는 덤프 전체를 메모리에 올리지 않아요. 파일을 범위별로 두 번 읽고, 읽는 대로 스크립트를 써요. 수 GB 덤프도 브라우저, 데스크톱 앱, 명령줄에서 변환돼요.
pg_dump -Fc 아카이브도 읽나요?
직접은 읽지 않아요. custom 아카이브는 바이너리 형식이에요. pg_restore -f dump.sql dump.backup을 실행하면 서버에 연결하지 않고 변환기가 읽는 일반 SQL로 바뀌어요. 아카이브를 받으면 변환기가 이렇게 알려 줘요.
어떤 PostgreSQL 버전의 덤프를 읽나요?
PostgreSQL 10 이상에서 pg_dump와 pg_dumpall로 만든, COPY 또는 INSERT 행이 담긴 덤프예요. 모든 테스트 덤프는 PostgreSQL 13과 18에서 만들고 원본과 셀 단위로 비교해요.
serial과 identity 값은 유지되나요?
네, 테이블마다 한 열이요. 기본 키의 첫 열인 serial 또는 identity 열은 AUTO_INCREMENT가 되고 가장 큰 id 다음부터 이어져요. MySQL은(는) 테이블마다 한 열만 번호를 매기므로 다른 열은 카운터 없이 값을 유지하고, 보고서에 그렇게 나와요.
배열, enum 등 PostgreSQL 타입은 어떻게 되나요?
배열은 JSON 배열, boolean은 tinyint(1), enum은 같은 레이블의 ENUM, money는 decimal이 돼요. 범위, 기하 타입, hstore, 복합 타입은 PostgreSQL의 텍스트를 유지하고, 보고서에 어떤 열인지 나와요.
함수, 트리거, 뷰는 어떻게 되나요?
데이터베이스마다 자체 언어로 작성하므로 변환하지 않고 보고서에 이름으로 나열해요.
스크립트는 어떤 MySQL 버전에서 불러올 수 있나요?
MySQL 5.7 이상이에요. 모든 테스트 덤프를 5.7과 9에서 불러오며, 문제가 생기면 첫 오류에서 멈춰요.