Chuyển đến nội dung
Trang chủ IntoSQL

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.

Tệp của bạn
sqlshop_2024_postgres.sqlTệp mẫu, 6,2 kB
Cơ sở dữ liệu của bạn

Đã chuyển đổi 18 hàng, 2 bản sửa, không hàng nào bị từ chối

Hiển thị

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
    IDNUMBER(10) not null
    NAMEVARCHAR2(4000 CHAR) not null
    EMAILVARCHAR2(750 CHAR) not null
    COUNTRYVARCHAR2(2 CHAR) not null
    IS_ACTIVENUMBER(1) not null
    TAGSCLOB not null
    SIGNED_UPDATE
    CREATED_ATTIMESTAMP(6) WITH TIME ZONE not null
  • ordersghi thành ORDERS10 hàng1
    10 cột
    IDNUMBER(10) not null
    CUSTOMER_IDNUMBER(10) not null
    STATUSVARCHAR2(9 CHAR) not null
    TOTALNUMBER(10,2) not null
    ITEMSNUMBER(5) not null
    ORDERED_ATTIMESTAMP(6) not null
    SHIPPED_ATTIMESTAMP(6)
    NOTEVARCHAR2(4000 CHAR)
    DETAILSCLOB
    DELIVERYVARCHAR2(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

  1. "tags" của customers là text[], kiểu Oracle không có, nên là CLOB với cùng giá trị.
  2. "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 PostgreSQLTrong OracleDòng báo cáo
booleanNUMBER(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.
textVARCHAR2(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 valuesNULLOracle 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
citextso 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 precisionNUMBER 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
moneyNUMBER(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
intervalVARCHAR2(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 typesVARCHAR2 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, jsonbCLOBCá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.
timestampTIMESTAMPtimestamp 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 zoneTIMESTAMP 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.
timeINTERVAL 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 9999NULLTậ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 numericNULLNUMBER 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 NULLbỏ 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 typesVARCHAR2 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 labelsVARCHAR2 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, macaddrVARCHAR2Oracle không có các kiểu như vậy; văn bản giữ mọi giá trị.
byteaBLOBByte vẫn là byte.
bit(n), bit varyingNUMBER 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, cidNUMBER(10) kèm CHECK không âmNUMBER chứa được mọi giá trị.
serial, identityGENERATED 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 tablemộ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 columnCREATE SEQUENCE, ở giá trị đã đạt tớiSequence của Oracle hoạt động theo cùng cách.
generated columnscộ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 lacksmộ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 sequencekhô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 lackskhô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 VALIDkhô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 columnskhô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 keyssau 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 DEFAULTbị 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 createkhô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 tablesmộ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
schemasmộ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 valuesNULLTrì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 knowCLOBVă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 encodingbyte 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.sql

Khó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ố.