Chuyển PostgreSQL sang Oracle
Thả bản dump dạng plain từ pg_dump hoặc pg_dumpall, dạng .sql hoặc .sql.gz, và tải xuống tập lệnh Oracle với cùng bảng, khóa, chỉ mục và dữ liệu. Mọi giá trị Oracle không chứa được nguyên trạng, và mọi đối tượng nó không hỗ trợ, đều được liệt kê trong báo cáo.
Đã chuyển đổi 18 hàng, 2 bản sửa, không hàng nào bị từ chối
Các bảng trong shop_2024_postgres.sqlBản dump PostgreSQL 18.6 · do pg_dump ghi · utf8mb4
customersghi thành CUSTOMERS8 hàng1
8 cột ID NUMBER(10) not null NAME VARCHAR2(4000 CHAR) not null EMAIL VARCHAR2(750 CHAR) not null COUNTRY VARCHAR2(2 CHAR) not null IS_ACTIVE NUMBER(1) not null TAGS CLOB not null SIGNED_UP DATE CREATED_AT TIMESTAMP(6) WITH TIME ZONE not null ordersghi thành ORDERS10 hàng1
10 cột ID NUMBER(10) not null CUSTOMER_ID NUMBER(10) not null STATUS VARCHAR2(9 CHAR) not null TOTAL NUMBER(10,2) not null ITEMS NUMBER(5) not null ORDERED_AT TIMESTAMP(6) not null SHIPPED_AT TIMESTAMP(6) NOTE VARCHAR2(4000 CHAR) DETAILS CLOB DELIVERY VARCHAR2(100 CHAR)
Không được chuyển đổi
- Khung nhìn paid_orders
Mỗi cơ sở dữ liệu viết các đối tượng này bằng ngôn ngữ riêng. Hãy viết lại chúng cho Oracle.
-- Written by IntoSQL from a PostgreSQL dump. Load it with: NLS_LANG=.AL32UTF8 sqlplus -S -L <user>/<password>@<database> @<file>
WHENEVER SQLERROR EXIT FAILURE ROLLBACK;
SET DEFINE OFF;
SET SQLBLANKLINES ON;
SET FEEDBACK OFF;
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION "INTOSQL_CLOB" (p SYS.ODCIVARCHAR2LIST) RETURN CLOB IS
r CLOB;
BEGIN
DBMS_LOB.CREATETEMPORARY(r, TRUE);
FOR i IN 1 .. p.COUNT LOOP
IF p(i) IS NOT NULL THEN
DBMS_LOB.WRITEAPPEND(r, LENGTH2(p(i)), p(i));
END IF;
END LOOP;
RETURN r;
END;
/
CREATE OR REPLACE FUNCTION "INTOSQL_BLOB" (p SYS.ODCIVARCHAR2LIST) RETURN BLOB IS
r BLOB;
piece RAW(2000);
BEGIN
DBMS_LOB.CREATETEMPORARY(r, TRUE);
FOR i IN 1 .. p.COUNT LOOP
piece := HEXTORAW(p(i));
DBMS_LOB.WRITEAPPEND(r, UTL_RAW.LENGTH(piece), piece);
END LOOP;
RETURN r;
END;
/
CREATE TABLE "CUSTOMERS" (
"ID" NUMBER(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1001),
"NAME" VARCHAR2(4000 CHAR) NOT NULL,
"EMAIL" VARCHAR2(750 CHAR) NOT NULL,
"COUNTRY" VARCHAR2(2 CHAR) DEFAULT 'US' NOT NULL,
"IS_ACTIVE" NUMBER(1) DEFAULT 1 NOT NULL,
"TAGS" CLOB NOT NULL,
"SIGNED_UP" DATE,
"CREATED_AT" TIMESTAMP(6) WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT "CK_CUSTOMERS_IS_ACTIVE" CHECK ("IS_ACTIVE" IN (0, 1))
);
CREATE TABLE "ORDERS" (
"ID" NUMBER(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 5001),
"CUSTOMER_ID" NUMBER(10) NOT NULL,
"STATUS" VARCHAR2(9 CHAR) DEFAULT 'pending' NOT NULL,
"TOTAL" NUMBER(10,2) NOT NULL,
"ITEMS" NUMBER(5) DEFAULT 1 NOT NULL,
"ORDERED_AT" TIMESTAMP(6) NOT NULL,
"SHIPPED_AT" TIMESTAMP(6),
"NOTE" VARCHAR2(4000 CHAR),
"DETAILS" CLOB,
"DELIVERY" VARCHAR2(100 CHAR),
CONSTRAINT "CK_ORDERS_STATUS" CHECK ("STATUS" IN ('pending', 'paid', 'shipped', 'cancelled')),
CONSTRAINT "ORDERS_TOTAL_CHECK" CHECK ("TOTAL" >= (0))
);
BEGIN
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"]',
DATE '2023-01-15',
TIMESTAMP '2023-01-15 10:24:00 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"TAGS",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
2,
'Zoë Müller',
'zoe@example.de',
'DE',
1,
'[]',
DATE '2023-02-03',
TIMESTAMP '2023-02-03 08:11:42 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"TAGS",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
3,
'José Peña',
'jose@example.es',
'ES',
0,
'["wholesale","late payer"]',
DATE '2023-03-21',
TIMESTAMP '2023-03-21 19:05:17 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"TAGS",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
4,
'李雷',
'lilei@example.cn',
'CN',
1,
'[]',
DATE '2023-05-09',
TIMESTAMP '2023-05-09 02:40:00 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"TAGS",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
5,
'Noah O''Brien',
'noah@example.ie',
'IE',
1,
'[]',
NULL,
TIMESTAMP '2023-06-30 14:00:00 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"TAGS",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
6,
'Amélie Laurent',
'amelie@example.fr',
'FR',
1,
'["vip"]',
DATE '2024-01-02',
TIMESTAMP '2024-01-02 09:30:00 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"TAGS",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
7,
'Ravi Patel',
'ravi@example.in',
'IN',
0,
'[]',
DATE '2024-02-29',
TIMESTAMP '2024-02-29 23:59:59 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"TAGS",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
8,
'Sofia Rossi 🌻',
'sofia@example.it',
'IT',
1,
'[]',
DATE '2024-04-12',
TIMESTAMP '2024-04-12 12:12:12 +00:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
1,
1,
'shipped',
129.90,
3,
TIMESTAMP '2024-03-01 10:00:00',
TIMESTAMP '2024-03-02 16:30:00',
NULL,
'{"gift": false}',
'1 day 06:30:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
2,
2,
'paid',
54.00,
1,
TIMESTAMP '2024-03-02 11:15:00',
NULL,
'Gift wrap 🎁',
'{"gift": true, "wrap": "red"}',
NULL
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
3,
1,
'cancelled',
12.50,
1,
TIMESTAMP '2024-03-03 09:45:00',
NULL,
'Customer changed their mind',
NULL,
NULL
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
4,
4,
'shipped',
980.00,
12,
TIMESTAMP '2024-03-05 02:10:00',
TIMESTAMP '2024-03-07 08:00:00',
'请小心轻放',
'{"fragile": true}',
'2 days 05:50:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
5,
5,
'pending',
45.75,
2,
TIMESTAMP '2024-03-08 17:20:00',
NULL,
'Leave at the door; ring twice',
NULL,
NULL
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
6,
6,
'shipped',
310.40,
5,
TIMESTAMP '2024-03-10 13:00:00',
TIMESTAMP '2024-03-11 09:00:00',
'Fragile: "glass"',
'{"fragile": true}',
'20:00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
7,
8,
'paid',
76.20,
2,
TIMESTAMP '2024-03-11 18:45:00',
NULL,
NULL,
NULL,
NULL
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
8,
2,
'shipped',
19.99,
1,
TIMESTAMP '2024-03-12 08:00:00',
NULL,
'Shipped date set to infinity by an old import',
NULL,
NULL
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
9,
3,
'shipped',
64.00,
2,
TIMESTAMP '2024-03-14 15:30:00',
TIMESTAMP '2024-03-15 10:00:00',
'Two parcels',
'{"parcels": [1, 2]}',
'18:30:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"DELIVERY"
) VALUES (
10,
7,
'paid',
1499.00,
1,
TIMESTAMP '2024-03-15 21:05:00',
NULL,
'C:\Users\ravi\invoice.pdf',
NULL,
NULL
);
COMMIT;
END;
/
-- Keys, indexes, foreign keys, counters and triggers, after the rows.
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "UQ_CUSTOMERS_CUSTOMERS_EMAIL_KEY" UNIQUE ("EMAIL");
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "PK_CUSTOMERS" PRIMARY KEY ("ID");
ALTER TABLE "ORDERS" ADD CONSTRAINT "PK_ORDERS" PRIMARY KEY ("ID");
CREATE INDEX "IX_ORDERS_IDX_ORDERS_CUSTOMER" ON "ORDERS" ("CUSTOMER_ID");
CREATE INDEX "IX_ORDERS_IDX_ORDERS_STATUS_DATE" ON "ORDERS" ("STATUS", "ORDERED_AT");
ALTER TABLE "ORDERS" ADD CONSTRAINT "ORDERS_CUSTOMER_ID_FKEY" FOREIGN KEY ("CUSTOMER_ID") REFERENCES "CUSTOMERS" ("ID") ENABLE NOVALIDATE;
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "ORDERS" ENABLE VALIDATE CONSTRAINT "ORDERS_CUSTOMER_ID_FKEY"';
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Foreign key ' || '"ORDERS_CUSTOMER_ID_FKEY"' || ' has rows without a parent: it stays unvalidated, and new rows are checked.');
END;
/
DECLARE
next_id NUMBER;
BEGIN
SELECT NVL(MAX("ID"), 0) + 1 INTO next_id FROM "CUSTOMERS";
IF next_id < 1001 THEN
next_id := 1001;
END IF;
EXECUTE IMMEDIATE 'ALTER TABLE "CUSTOMERS" MODIFY ("ID" GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH ' || next_id || '))';
END;
/
COMMENT ON TABLE "CUSTOMERS" IS 'People who bought at least once';
DECLARE
next_id NUMBER;
BEGIN
SELECT NVL(MAX("ID"), 0) + 1 INTO next_id FROM "ORDERS";
IF next_id < 5001 THEN
next_id := 5001;
END IF;
EXECUTE IMMEDIATE 'ALTER TABLE "ORDERS" MODIFY ("ID" GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH ' || next_id || '))';
END;
/
DROP FUNCTION "INTOSQL_CLOB";
DROP FUNCTION "INTOSQL_BLOB";
COMMIT;
EXIT;
Bản sửa
- "tags" của customers là text[], kiểu Oracle không có, nên là CLOB với cùng giá trị.
- "delivery" của orders là interval, kiểu Oracle không có, nên là VARCHAR2(100 CHAR) với cùng giá trị.
Cần xem lại
- 1 khung nhìn, trình kích hoạt, thủ tục hoặc sự kiện không được chuyển đổi; báo cáo liệt kê từng mục. Hãy tạo lại chúng thủ công trong Oracle.
- Giá trị mặc định của "tags" trong customers không viết được cho Oracle (a value its type can't hold), nên cột không có giá trị mặc định. Hãy thêm giá trị mặc định thủ công nếu hàng mới cần nó.
- Chỉ mục idx_orders_details trên orders dùng một biểu thức không viết được cho Oracle (a gin index), nên không được tạo. Hãy tạo chỉ mục thủ công nếu truy vấn cần nó.
- 1 giá trị trong "shipped_at" của orders là ngày mà Oracle không lưu được, như infinity, nên chúng là NULL. Oracle lưu năm từ 1 đến 9999, không có vô cực; hãy thay các ngày đó trong nguồn nếu chúng quan trọng.
Tệp được chuyển đổi ngay trên máy tính này và không bao giờ được tải lên.
Mẫu khác:
Những gì thay đổi từ PostgreSQL sang Oracle
Mỗi hàng là một quy tắc trình chuyển đổi áp dụng, kèm dòng báo cáo được ghi khi quy tắc thay đổi dữ liệu của bạn.
boolean
NUMBER(1) kèm CHECK 0 và 1
Oracle 21c không có kiểu cột boolean; 1 và 0 giữ true và false trên mọi phiên bản.
varchar(n), char(n)
VARCHAR2(n CHAR), đếm theo ký tự
Độ dài đếm theo ký tự như PostgreSQL.
text
VARCHAR2(4000 CHAR) khi mọi giá trị vừa 4000 byte (750 ký tự trong khóa), nếu không thì CLOB
VARCHAR2 mặc định chứa 4000 byte và Oracle không lập chỉ mục được CLOB, nên văn bản giữ VARCHAR2 khi giá trị vừa và là CLOB khi không vừa.
Dòng báo cáo: text_as_lob
empty strings and empty bytea values
NULL
Oracle lưu chuỗi rỗng là NULL, nên giá trị từng là ' được đọc lại là NULL. Báo cáo đếm chúng theo từng cột.
Dòng báo cáo: empty_string_null
citext
so sánh chính xác
Oracle so sánh văn bản chính xác, trừ khi được chỉ định khác, như văn bản của PostgreSQL; cột citext mất khả năng bỏ qua hoa thường.
Dòng báo cáo: case_insensitive_collation
numeric(p,s) past 38 digits; numeric without a precision
NUMBER khi giá trị vừa 38 chữ số, nếu không thì VARCHAR2
NUMBER của Oracle chứa 38 chữ số ở mọi số chữ số thập phân. Số rộng hơn được giữ dạng văn bản để mọi chữ số vẫn chính xác.
Dòng báo cáo: decimal_as_text
money
NUMBER(19,2)
Oracle không có kiểu tiền tệ. Số tiền được giữ dạng số, không kèm ký hiệu tiền tệ mà locale của máy chủ đã thêm.
Dòng báo cáo: type_replaced
interval
VARCHAR2(100 CHAR) với văn bản của PostgreSQL
interval trộn tháng với ngày và giây, mà Oracle giữ ở hai kiểu khác nhau; văn bản giữ mọi phần.
Dòng báo cáo: type_replaced
arrays (integer[], text[]...)
CLOB chứa mảng JSON
Oracle không có mảng. Mảng JSON giữ mọi phần tử và NULL, và JSON_TABLE đọc được nó.
Dòng báo cáo: type_replaced
ranges, geometric types, tsvector, xml, hstore, PostGIS, composite and extension types
VARCHAR2 hoặc CLOB với văn bản của PostgreSQL
Oracle không có kiểu tương đương, nên mỗi giá trị giữ văn bản PostgreSQL đã ghi.
Dòng báo cáo: type_replaced
json, jsonb
CLOB
Các hàm JSON của Oracle đọc JSON từ văn bản trên mọi phiên bản, và CLOB giữ giá trị ở mọi kích thước.
timestamp
TIMESTAMP
timestamp không có múi giờ là thời gian theo đồng hồ, giống TIMESTAMP của Oracle. date thành DATE, kiểu cũng chứa giờ trong ngày, luôn ở nửa đêm.
timestamp with time zone
TIMESTAMP WITH TIME ZONE theo UTC
Mỗi giá trị được ghi theo UTC, cùng một thời điểm dù bản dump ghi độ lệch nào.
time
INTERVAL DAY TO SECOND tính từ nửa đêm
Oracle không có kiểu giờ trong ngày; interval tính từ nửa đêm chứa mọi giá trị, kể cả 24:00:00.
infinity, -infinity, BC dates and years past 9999
NULL
Tập lệnh ghi năm từ 1 đến 9999, và Oracle không có vô cực. Các giá trị đó trở thành NULL và báo cáo đếm số lượng.
Dòng báo cáo: date_out_of_range
NaN and Infinity in numeric
NULL
NUMBER của Oracle không có NaN hay Infinity, nên các giá trị đó trở thành NULL và báo cáo đếm số lượng.
Dòng báo cáo: invalid_value_null
NOT NULL columns with values that become NULL
bỏ NOT NULL
Cột có giá trị phải chuyển thành NULL không thể giữ NOT NULL, nếu không quá trình nạp sẽ dừng.
Dòng báo cáo: not_null_relaxed
enum types
VARCHAR2 kèm CHECK các nhãn
Văn bản kèm ràng buộc kiểm tra giữ đúng các giá trị.
enum columns holding values outside their labels
VARCHAR2 không có ràng buộc kiểm tra
Giá trị không có trong các nhãn sẽ vi phạm ràng buộc kiểm tra, nên ràng buộc không được tạo.
Dòng báo cáo: enum_check_skipped
uuid, inet, cidr, macaddr
VARCHAR2
Oracle không có các kiểu như vậy; văn bản giữ mọi giá trị.
bytea
BLOB
Byte vẫn là byte.
bit(n), bit varying
NUMBER với giá trị của các bit đến 63 bit; dài hơn là chữ số dạng text
Chuỗi bit được lưu là số do các bit tạo thành.
oid, xid, cid
NUMBER(10) kèm CHECK không âm
NUMBER chứa được mọi giá trị.
serial, identity
GENERATED BY DEFAULT ON NULL AS IDENTITY, tiếp tục sau id lớn nhất
Các id đã sao chép được nạp nguyên trạng, và bộ đếm tiếp tục sau id lớn nhất hoặc giá trị kế tiếp của sequence, tùy giá trị nào lớn hơn.
a second serial or identity column in a table
một số nguyên thường
Oracle đếm một cột identity mỗi bảng; cột khác giữ giá trị mà không có bộ đếm.
Dòng báo cáo: counter_dropped
sequences not owned by a column
CREATE SEQUENCE, ở giá trị đã đạt tới
Sequence của Oracle hoạt động theo cùng cách.
generated columns
cột ảo
Oracle chỉ tính cột tính toán khi đọc; cột STORED thành cột ảo với cùng giá trị.
Dòng báo cáo: stored_as_virtual
generated columns with functions Oracle lacks
một cột thường với các giá trị
Công thức không viết được cho Oracle để lại một cột thường với giá trị của bản dump và một dòng trong báo cáo.
Dòng báo cáo: generated_not_translated
defaults with functions Oracle lacks, and defaults from a sequence
không có giá trị mặc định
Giá trị mặc định không viết được cho Oracle sẽ bị bỏ và được báo cáo.
Dòng báo cáo: default_not_translated
CHECK constraints
được chuyển đổi, viết trực tiếp trong CREATE TABLE
Ràng buộc viết trực tiếp được kiểm tra khi nạp từng hàng.
CHECK constraints with functions Oracle lacks
không được tạo
Ràng buộc kiểm tra không viết được cho Oracle sẽ bị bỏ và được báo cáo.
Dòng báo cáo: check_skipped
CHECK ... NOT VALID
không được tạo
PostgreSQL chưa bao giờ kiểm tra các hàng có từ trước, nên chúng có thể vi phạm ràng buộc.
Dòng báo cáo: check_not_valid
gin, gist, brin and hash indexes, partial and expression indexes, and indexes on CLOB columns
không được tạo
IntoSQL ghi chỉ mục b-tree trên cột cho Oracle, vốn không lập chỉ mục được CLOB; hãy tạo lại các chỉ mục khác sau khi nạp.
Dòng báo cáo: index_skipped
foreign keys
sau dữ liệu ENABLE NOVALIDATE, rồi xác thực kèm cảnh báo về hàng mồ côi
Khóa kiểm tra hàng mới ngay và được xác thực sau cùng; hàng không có hàng cha khiến khóa ở trạng thái chưa xác thực kèm cảnh báo thay vì dừng quá trình nạp.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT
bị bỏ
Khóa ngoại của Oracle chỉ tác động khi xóa, với CASCADE hoặc SET NULL.
Dòng báo cáo: foreign_key_action_unsupported
foreign keys to tables the dump doesn't create
không được tạo
Khóa không thể tham chiếu tới bảng không tồn tại.
Dòng báo cáo: foreign_key_skipped
names over 128 bytes
được rút ngắn
Tên trong Oracle 12.2 trở lên tối đa 128 byte, nhiều hơn 63 của PostgreSQL.
Dòng báo cáo: name_shortened
partitioned tables
một bảng chứa các hàng của mọi phân vùng
Các hàng giữ nguyên; hãy phân vùng lại bảng trong Oracle nếu cần.
Dòng báo cáo: partitions_dropped
schemas
một schema, mỗi bảng có tên schema ở đầu
Tập lệnh nạp vào schema của người dùng chạy nó, nên bảng của các schema khác nhau có tên schema ở đầu; bảng trong public giữ tên.
Dòng báo cáo: schemas_merged
views, functions, procedures, triggers, rules, policies, extensions and types
được liệt kê trong báo cáo
Mã của chúng viết bằng ngôn ngữ của PostgreSQL, nên được liệt kê để bạn tạo lại.
Dòng báo cáo: not_converted_objects
dumps without CREATE TABLE (--data-only)
kiểu suy ra từ giá trị
Bản dump chỉ có dữ liệu thì chỉ có các hàng, nên kiểu được suy ra từ giá trị.
Dòng báo cáo: no_schema
expressions in INSERT values
NULL
Trình chuyển đổi không chạy cơ sở dữ liệu thì không tính được chúng.
Dòng báo cáo: expression_value
types IntoSQL doesn't know
CLOB
Văn bản chứa được mọi giá trị; hãy đổi kiểu sau khi nạp.
Dòng báo cáo: unknown_type
text that isn't valid in its encoding
byte lỗi thành ký tự thay thế
Tập lệnh là UTF-8 và nạp với NLS_LANG=.AL32UTF8.
Dòng báo cáo: invalid_utf8_replaced
text decoded twice (ñ)
sao chép nguyên trạng
Bản dump chứa đúng các ký tự này, nên chúng được sao chép; báo cáo chỉ ra chúng.
Dòng báo cáo: mojibake_suspected
| Trong PostgreSQL | Trong Oracle | Dòng báo cáo |
|---|---|---|
| boolean | NUMBER(1) kèm CHECK 0 và 1Oracle 21c không có kiểu cột boolean; 1 và 0 giữ true và false trên mọi phiên bản. | |
| varchar(n), char(n) | VARCHAR2(n CHAR), đếm theo ký tựĐộ dài đếm theo ký tự như PostgreSQL. | |
| text | VARCHAR2(4000 CHAR) khi mọi giá trị vừa 4000 byte (750 ký tự trong khóa), nếu không thì CLOBVARCHAR2 mặc định chứa 4000 byte và Oracle không lập chỉ mục được CLOB, nên văn bản giữ VARCHAR2 khi giá trị vừa và là CLOB khi không vừa. | text_as_lob |
| empty strings and empty bytea values | NULLOracle lưu chuỗi rỗng là NULL, nên giá trị từng là ' được đọc lại là NULL. Báo cáo đếm chúng theo từng cột. | empty_string_null |
| citext | so sánh chính xácOracle so sánh văn bản chính xác, trừ khi được chỉ định khác, như văn bản của PostgreSQL; cột citext mất khả năng bỏ qua hoa thường. | case_insensitive_collation |
| numeric(p,s) past 38 digits; numeric without a precision | NUMBER khi giá trị vừa 38 chữ số, nếu không thì VARCHAR2NUMBER của Oracle chứa 38 chữ số ở mọi số chữ số thập phân. Số rộng hơn được giữ dạng văn bản để mọi chữ số vẫn chính xác. | decimal_as_text |
| money | NUMBER(19,2)Oracle không có kiểu tiền tệ. Số tiền được giữ dạng số, không kèm ký hiệu tiền tệ mà locale của máy chủ đã thêm. | type_replaced |
| interval | VARCHAR2(100 CHAR) với văn bản của PostgreSQLinterval trộn tháng với ngày và giây, mà Oracle giữ ở hai kiểu khác nhau; văn bản giữ mọi phần. | type_replaced |
| arrays (integer[], text[]...) | CLOB chứa mảng JSONOracle không có mảng. Mảng JSON giữ mọi phần tử và NULL, và JSON_TABLE đọc được nó. | type_replaced |
| ranges, geometric types, tsvector, xml, hstore, PostGIS, composite and extension types | VARCHAR2 hoặc CLOB với văn bản của PostgreSQLOracle không có kiểu tương đương, nên mỗi giá trị giữ văn bản PostgreSQL đã ghi. | type_replaced |
| json, jsonb | CLOBCác hàm JSON của Oracle đọc JSON từ văn bản trên mọi phiên bản, và CLOB giữ giá trị ở mọi kích thước. | |
| timestamp | TIMESTAMPtimestamp không có múi giờ là thời gian theo đồng hồ, giống TIMESTAMP của Oracle. date thành DATE, kiểu cũng chứa giờ trong ngày, luôn ở nửa đêm. | |
| timestamp with time zone | TIMESTAMP WITH TIME ZONE theo UTCMỗi giá trị được ghi theo UTC, cùng một thời điểm dù bản dump ghi độ lệch nào. | |
| time | INTERVAL DAY TO SECOND tính từ nửa đêmOracle không có kiểu giờ trong ngày; interval tính từ nửa đêm chứa mọi giá trị, kể cả 24:00:00. | |
| infinity, -infinity, BC dates and years past 9999 | NULLTập lệnh ghi năm từ 1 đến 9999, và Oracle không có vô cực. Các giá trị đó trở thành NULL và báo cáo đếm số lượng. | date_out_of_range |
| NaN and Infinity in numeric | NULLNUMBER của Oracle không có NaN hay Infinity, nên các giá trị đó trở thành NULL và báo cáo đếm số lượng. | invalid_value_null |
| NOT NULL columns with values that become NULL | bỏ NOT NULLCột có giá trị phải chuyển thành NULL không thể giữ NOT NULL, nếu không quá trình nạp sẽ dừng. | not_null_relaxed |
| enum types | VARCHAR2 kèm CHECK các nhãnVăn bản kèm ràng buộc kiểm tra giữ đúng các giá trị. | |
| enum columns holding values outside their labels | VARCHAR2 không có ràng buộc kiểm traGiá trị không có trong các nhãn sẽ vi phạm ràng buộc kiểm tra, nên ràng buộc không được tạo. | enum_check_skipped |
| uuid, inet, cidr, macaddr | VARCHAR2Oracle không có các kiểu như vậy; văn bản giữ mọi giá trị. | |
| bytea | BLOBByte vẫn là byte. | |
| bit(n), bit varying | NUMBER với giá trị của các bit đến 63 bit; dài hơn là chữ số dạng textChuỗi bit được lưu là số do các bit tạo thành. | |
| oid, xid, cid | NUMBER(10) kèm CHECK không âmNUMBER chứa được mọi giá trị. | |
| serial, identity | GENERATED BY DEFAULT ON NULL AS IDENTITY, tiếp tục sau id lớn nhấtCác id đã sao chép được nạp nguyên trạng, và bộ đếm tiếp tục sau id lớn nhất hoặc giá trị kế tiếp của sequence, tùy giá trị nào lớn hơn. | |
| a second serial or identity column in a table | một số nguyên thườngOracle đếm một cột identity mỗi bảng; cột khác giữ giá trị mà không có bộ đếm. | counter_dropped |
| sequences not owned by a column | CREATE SEQUENCE, ở giá trị đã đạt tớiSequence của Oracle hoạt động theo cùng cách. | |
| generated columns | cột ảoOracle chỉ tính cột tính toán khi đọc; cột STORED thành cột ảo với cùng giá trị. | stored_as_virtual |
| generated columns with functions Oracle lacks | một cột thường với các giá trịCông thức không viết được cho Oracle để lại một cột thường với giá trị của bản dump và một dòng trong báo cáo. | generated_not_translated |
| defaults with functions Oracle lacks, and defaults from a sequence | không có giá trị mặc địnhGiá trị mặc định không viết được cho Oracle sẽ bị bỏ và được báo cáo. | default_not_translated |
| CHECK constraints | được chuyển đổi, viết trực tiếp trong CREATE TABLERàng buộc viết trực tiếp được kiểm tra khi nạp từng hàng. | |
| CHECK constraints with functions Oracle lacks | không được tạoRàng buộc kiểm tra không viết được cho Oracle sẽ bị bỏ và được báo cáo. | check_skipped |
| CHECK ... NOT VALID | không được tạoPostgreSQL chưa bao giờ kiểm tra các hàng có từ trước, nên chúng có thể vi phạm ràng buộc. | check_not_valid |
| gin, gist, brin and hash indexes, partial and expression indexes, and indexes on CLOB columns | không được tạoIntoSQL ghi chỉ mục b-tree trên cột cho Oracle, vốn không lập chỉ mục được CLOB; hãy tạo lại các chỉ mục khác sau khi nạp. | index_skipped |
| foreign keys | sau dữ liệu ENABLE NOVALIDATE, rồi xác thực kèm cảnh báo về hàng mồ côiKhóa kiểm tra hàng mới ngay và được xác thực sau cùng; hàng không có hàng cha khiến khóa ở trạng thái chưa xác thực kèm cảnh báo thay vì dừng quá trình nạp. | |
| ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT | bị bỏKhóa ngoại của Oracle chỉ tác động khi xóa, với CASCADE hoặc SET NULL. | foreign_key_action_unsupported |
| foreign keys to tables the dump doesn't create | không được tạoKhóa không thể tham chiếu tới bảng không tồn tại. | foreign_key_skipped |
| names over 128 bytes | được rút ngắnTên trong Oracle 12.2 trở lên tối đa 128 byte, nhiều hơn 63 của PostgreSQL. | name_shortened |
| partitioned tables | một bảng chứa các hàng của mọi phân vùngCác hàng giữ nguyên; hãy phân vùng lại bảng trong Oracle nếu cần. | partitions_dropped |
| schemas | một schema, mỗi bảng có tên schema ở đầuTập lệnh nạp vào schema của người dùng chạy nó, nên bảng của các schema khác nhau có tên schema ở đầu; bảng trong public giữ tên. | schemas_merged |
| views, functions, procedures, triggers, rules, policies, extensions and types | được liệt kê trong báo cáoMã của chúng viết bằng ngôn ngữ của PostgreSQL, nên được liệt kê để bạn tạo lại. | not_converted_objects |
| dumps without CREATE TABLE (--data-only) | kiểu suy ra từ giá trịBản dump chỉ có dữ liệu thì chỉ có các hàng, nên kiểu được suy ra từ giá trị. | no_schema |
| expressions in INSERT values | NULLTrình chuyển đổi không chạy cơ sở dữ liệu thì không tính được chúng. | expression_value |
| types IntoSQL doesn't know | CLOBVăn bản chứa được mọi giá trị; hãy đổi kiểu sau khi nạp. | unknown_type |
| text that isn't valid in its encoding | byte lỗi thành ký tự thay thếTập lệnh là UTF-8 và nạp với NLS_LANG=.AL32UTF8. | invalid_utf8_replaced |
| text decoded twice (ñ) | sao chép nguyên trạngBản dump chứa đúng các ký tự này, nên chúng được sao chép; báo cáo chỉ ra chúng. | mojibake_suspected |
Nạp tập lệnh vào Oracle
Tập lệnh tạo bảng, sao chép các hàng, rồi thêm khóa, chỉ mục và khóa ngoại, nên nạp nhanh và dừng ở lỗi đầu tiên.
NLS_LANG=.AL32UTF8 sqlplus -S -L user@//localhost/mydb @postgresql.oracle.sqlKhóa ngoại được thêm với ENABLE NOVALIDATE, nên hàng mới được kiểm tra ngay, rồi được xác thực. Nếu một hàng cũ trỏ tới hàng không tồn tại, tập lệnh cho biết ràng buộc nào và để nó ở trạng thái chưa xác thực, thay vì thất bại giữa chừng.
Với bản dump lớn, hãy chạy SQL*Plus trên cùng máy với cơ sở dữ liệu. Tập lệnh commit sau mỗi 100 hàng. Người dùng chạy tập lệnh cần quyền CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER và CREATE PROCEDURE, cùng hạn mức trên tablespace của mình.
Tạo bản dump PostgreSQL để có kết quả tốt nhất
Trình chuyển đổi đọc những gì bản dump chứa. Các tùy chọn sau giữ lại nhiều dữ liệu hơn trong đó:
- --format=plain, mặc định của pg_dump, ghi ra SQL. Kho lưu trữ custom hoặc directory (-Fc, -Fd) thành SQL bằng pg_restore -f dump.sql, không cần máy chủ cơ sở dữ liệu.
- --no-owner --no-privileges bỏ vai trò và quyền, những thứ trình chuyển đổi vốn bỏ qua, nên bản dump nhỏ hơn.
- pg_dumpall dump mọi cơ sở dữ liệu vào một tệp; bảng của mỗi cơ sở dữ liệu có tên của nó ở đầu, nên không có gì trùng.
Những gì không được chuyển đổi
Khung nhìn, khung nhìn cụ thể hóa, hàm, thủ tục, trình kích hoạt, quy tắc, chính sách bảo mật cấp hàng, tiện ích mở rộng và kiểu được viết bằng ngôn ngữ riêng của PostgreSQL. Chúng được liệt kê theo tên trong báo cáo, không bao giờ bị bỏ âm thầm, để bạn viết lại cho Oracle.
Câu hỏi về PostgreSQL sang Oracle
Chưa có câu trả lời ở đây? Hãy viết cho chúng tôi từ trang liên hệ, sẽ có người trả lời. Trang liên hệ
Bản dump của tôi có bị tải lên không?
Không. Trình chuyển đổi chạy trong trình duyệt và đọc bản dump từ ổ đĩa theo từng phần, nên nó không bao giờ rời khỏi máy tính của bạn. Ứng dụng máy tính và dòng lệnh cũng chuyển đổi ngay trên máy tính của bạn.
Bản dump có thể lớn đến đâu?
Trình chuyển đổi không bao giờ giữ toàn bộ bản dump trong bộ nhớ: nó đọc tệp hai lần, theo từng đoạn, và ghi tập lệnh trong lúc đọc. Bản dump nhiều gigabyte vẫn chuyển đổi được trong trình duyệt, trong ứng dụng máy tính và bằng dòng lệnh.
Nó có đọc được kho lưu trữ pg_dump -Fc không?
Không trực tiếp: kho lưu trữ custom là định dạng nhị phân. pg_restore -f dump.sql dump.backup chuyển nó thành SQL dạng plain mà trình chuyển đổi đọc được, không cần kết nối máy chủ. Trình chuyển đổi sẽ báo khi nhận một kho lưu trữ.
Bản dump có thể đến từ những phiên bản PostgreSQL nào?
Bản dump do pg_dump và pg_dumpall ghi từ PostgreSQL 10 trở lên, với các hàng COPY hoặc INSERT. Mọi bản dump thử nghiệm đến từ PostgreSQL 13 và 18 và được so với nguồn từng ô một.
Giá trị serial và identity có được giữ không?
Có. Cột serial hoặc identity của mỗi bảng trở thành cột identity, mọi hàng giữ id của nó, và id tiếp theo tiếp tục sau id lớn nhất. Sequence không thuộc cột nào thành sequence Oracle ở giá trị đã đạt tới.
Mảng, enum và các kiểu PostgreSQL khác sẽ ra sao?
Mảng thành mảng JSON, boolean thành NUMBER(1), timestamp có múi giờ thành TIMESTAMP WITH TIME ZONE, và văn bản thành VARCHAR2 khi giá trị vừa, nếu không thì CLOB. Chuỗi rỗng thành NULL, vì Oracle lưu chúng như vậy, và báo cáo đếm chúng.
Còn hàm, trình kích hoạt và khung nhìn thì sao?
Chúng được liệt kê theo tên trong báo cáo và không được chuyển đổi, vì mỗi cơ sở dữ liệu viết chúng bằng ngôn ngữ riêng.
Tập lệnh nạp được trên những phiên bản Oracle nào?
Oracle 19c trở lên. Mọi bản dump thử nghiệm đều nạp được trên 21c và 23ai, và dừng ở lỗi đầu tiên nếu có sự cố.