Zum Inhalt springen
IntoSQL-Startseite

PostgreSQL in Oracle umwandeln

Leg einen einfachen Dump aus pg_dump oder pg_dumpall ab, als .sql oder .sql.gz, und lade ein Oracle-Skript mit denselben Tabellen, Schlüsseln, Indizes und Daten herunter. Jeder Wert, den Oracle nicht unverändert aufnehmen kann, und jedes Objekt, das es nicht übernimmt, steht im Bericht.

Deine Datei
sqlshop_2024_postgres.sqlBeispieldatei, 6,2 kB
Deine Datenbank

18 Zeilen konvertiert, 2 Korrekturen, keine abgelehnt

Anzeigen

Tabellen in shop_2024_postgres.sqlPostgreSQL-18.6-Dump · erstellt mit pg_dump · utf8mb4

  • customersgeschrieben als CUSTOMERS8 Zeilen1
    8 Spalten
    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
  • ordersgeschrieben als ORDERS10 Zeilen1
    10 Spalten
    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)

Nicht konvertiert

  • Sicht paid_orders

Jede Datenbank schreibt diese in ihrer eigenen Sprache. Schreib sie für Oracle neu.

-- 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;

Korrekturen

  1. "tags" von customers ist text[], was Oracle nicht hat, daher ist sie CLOB mit denselben Werten.
  2. "delivery" von orders ist interval, was Oracle nicht hat, daher ist sie VARCHAR2(100 CHAR) mit denselben Werten.

Zu prüfen

  • 1 Sicht, Trigger, Routine oder Ereignis wird nicht konvertiert; der Bericht listet sie einzeln auf. Lege sie in Oracle von Hand neu an.
  • Der Standardwert von "tags" in customers lässt sich nicht für Oracle schreiben (a value its type can't hold), daher hat die Spalte keinen Standardwert. Füge den Standardwert von Hand hinzu, wenn neue Zeilen ihn brauchen.
  • Der Index idx_orders_details auf orders nutzt einen Ausdruck, der sich nicht für Oracle schreiben lässt (a gin index), daher wird er nicht angelegt. Lege den Index von Hand an, wenn Abfragen ihn brauchen.
  • 1 Wert in "shipped_at" von orders ist ein Datum, das Oracle nicht speichern kann, etwa infinity, daher ist er NULL. Oracle speichert die Jahre 1 bis 9999, ohne Unendlich; ersetze diese Datumsangaben in der Quelle, wenn sie wichtig sind.

Deine Datei wird auf diesem Computer umgewandelt und nie hochgeladen.

Weitere Beispiele:

Was sich von PostgreSQL zu Oracle ändert

Jede Zeile ist eine Regel, die der Konverter anwendet, mit der Berichtszeile, die er schreibt, wenn die Regel etwas an deinen Daten ändert.

  • boolean

    NUMBER(1) mit einem CHECK auf 0 und 1

    Oracle 21c hat keinen booleschen Spaltentyp; 1 und 0 bewahren true und false auf jeder Version.

  • varchar(n), char(n)

    VARCHAR2(n CHAR), in Zeichen gezählt

    Längen zählen Zeichen wie in PostgreSQL.

  • text

    VARCHAR2(4000 CHAR), wenn jeder Wert in 4000 Bytes passt (750 Zeichen in einem Schlüssel), sonst CLOB

    Ein VARCHAR2 fasst standardmäßig 4000 Bytes, und Oracle kann kein CLOB indizieren, daher behält Text VARCHAR2, wenn seine Werte passen, und wird sonst ein CLOB.

    Berichtszeile: text_as_lob

  • empty strings and empty bytea values

    NULL

    Oracle speichert einen leeren String als NULL, daher wird ein Wert, der ' war, als NULL gelesen. Der Bericht zählt sie pro Spalte.

    Berichtszeile: empty_string_null

  • citext

    exakter Vergleich

    Oracle vergleicht Text exakt, sofern nicht anders angegeben, wie text in PostgreSQL; citext-Spalten vergleichen nicht mehr ohne Groß-/Kleinschreibung.

    Berichtszeile: case_insensitive_collation

  • numeric(p,s) past 38 digits; numeric without a precision

    NUMBER, wenn seine Werte in 38 Stellen passen, sonst VARCHAR2

    NUMBER in Oracle fasst 38 Stellen bei jeder Skalierung. Breitere Zahlen bleiben Text, damit jede Stelle exakt bleibt.

    Berichtszeile: decimal_as_text

  • money

    NUMBER(19,2)

    Oracle hat keinen money-Typ. Der Betrag bleibt eine Zahl, ohne das Währungssymbol, das die Locale des Servers hinzugefügt hat.

    Berichtszeile: type_replaced

  • interval

    VARCHAR2(100 CHAR) mit dem Text von PostgreSQL

    Ein interval mischt Monate mit Tagen und Sekunden, die Oracle in zwei verschiedenen Typen hält; der Text behält jeden Teil.

    Berichtszeile: type_replaced

  • arrays (integer[], text[]...)

    CLOB mit einem JSON-Array

    Oracle hat keine Arrays. Ein JSON-Array behält jedes Element und NULL, und JSON_TABLE liest es.

    Berichtszeile: type_replaced

  • ranges, geometric types, tsvector, xml, hstore, PostGIS, composite and extension types

    VARCHAR2 oder CLOB mit dem Text von PostgreSQL

    Oracle hat keinen entsprechenden Typ, daher behält jeder Wert den Text, den PostgreSQL geschrieben hat.

    Berichtszeile: type_replaced

  • json, jsonb

    CLOB

    Die JSON-Funktionen von Oracle lesen JSON auf jeder Version aus Text, und ein CLOB fasst Werte jeder Größe.

  • timestamp

    TIMESTAMP

    Ein timestamp without time zone ist eine Uhrzeitangabe ohne Zeitzone, wie TIMESTAMP in Oracle. date wird DATE, das auch eine Uhrzeit enthält, die auf Mitternacht bleibt.

  • timestamp with time zone

    TIMESTAMP WITH TIME ZONE in UTC

    Jeder Wert wird in UTC geschrieben: derselbe Zeitpunkt, welchen Versatz der Dump auch geschrieben hat.

  • time

    INTERVAL DAY TO SECOND ab Mitternacht

    Oracle hat keinen Uhrzeittyp; ein Intervall ab Mitternacht fasst jeden Wert, einschließlich 24:00:00.

  • infinity, -infinity, BC dates and years past 9999

    NULL

    Das Skript schreibt die Jahre 1 bis 9999, und Oracle kennt kein Unendlich. Diese Werte werden NULL, und der Bericht zählt sie.

    Berichtszeile: date_out_of_range

  • NaN and Infinity in numeric

    NULL

    NUMBER in Oracle kennt weder NaN noch Infinity, daher werden diese Werte NULL, und der Bericht zählt sie.

    Berichtszeile: invalid_value_null

  • NOT NULL columns with values that become NULL

    NOT NULL entfernt

    Eine Spalte, deren Werte NULL werden mussten, kann NOT NULL nicht behalten, sonst würde das Laden abbrechen.

    Berichtszeile: not_null_relaxed

  • enum types

    VARCHAR2 mit einem CHECK seiner Labels

    Text mit einer CHECK-Bedingung behält dieselben Werte.

  • enum columns holding values outside their labels

    VARCHAR2 ohne CHECK

    Werte, die nicht unter den Labels stehen, würden die CHECK-Bedingung verletzen, daher wird sie nicht angelegt.

    Berichtszeile: enum_check_skipped

  • uuid, inet, cidr, macaddr

    VARCHAR2

    Oracle hat solche Typen nicht; der Text behält jeden Wert.

  • bytea

    BLOB

    Bytes bleiben Bytes.

  • bit(n), bit varying

    NUMBER mit dem Wert der Bits bis 63 Bit; darüber Ziffern als Text

    Bitstrings werden als die Zahl gespeichert, die ihre Bits ergeben.

  • oid, xid, cid

    NUMBER(10) mit einem CHECK gegen negative Werte

    NUMBER fasst jeden Wert.

  • serial, identity

    GENERATED BY DEFAULT ON NULL AS IDENTITY, weiter nach der höchsten ID

    Die kopierten IDs laden unverändert, und der Zähler macht nach der höchsten weiter oder beim nächsten Wert der Sequenz, je nachdem, was höher ist.

  • a second serial or identity column in a table

    eine normale Ganzzahl

    Oracle zählt eine Identity-Spalte pro Tabelle; jede andere behält ihre Werte ohne Zähler.

    Berichtszeile: counter_dropped

  • sequences not owned by a column

    CREATE SEQUENCE, bei dem Wert, den sie erreicht hatte

    Sequenzen in Oracle funktionieren genauso.

  • generated columns

    virtuelle Spalten

    Oracle berechnet generierte Spalten nur beim Lesen; STORED-Spalten werden virtuell, mit denselben Werten.

    Berichtszeile: stored_as_virtual

  • generated columns with functions Oracle lacks

    eine normale Spalte mit den Werten

    Eine Formel, die sich nicht für Oracle schreiben lässt, hinterlässt eine normale Spalte mit den Werten des Dumps und eine Zeile im Bericht.

    Berichtszeile: generated_not_translated

  • defaults with functions Oracle lacks, and defaults from a sequence

    kein Standardwert

    Ein Standardwert, der sich nicht für Oracle schreiben lässt, wird weggelassen und gemeldet.

    Berichtszeile: default_not_translated

  • CHECK constraints

    übersetzt, inline in CREATE TABLE

    Inline-CHECK-Bedingungen werden beim Laden jeder Zeile geprüft.

  • CHECK constraints with functions Oracle lacks

    nicht angelegt

    Eine CHECK-Bedingung, die sich nicht für Oracle schreiben lässt, wird weggelassen und gemeldet.

    Berichtszeile: check_skipped

  • CHECK ... NOT VALID

    nicht angelegt

    PostgreSQL hat die vorher vorhandenen Zeilen nie geprüft, daher können sie die CHECK-Bedingung verletzen.

    Berichtszeile: check_not_valid

  • gin, gist, brin and hash indexes, partial and expression indexes, and indexes on CLOB columns

    nicht angelegt

    IntoSQL schreibt für Oracle B-Tree-Indizes auf Spalten, und Oracle kann kein CLOB indizieren; lege die anderen nach dem Laden neu an.

    Berichtszeile: index_skipped

  • foreign keys

    nach den Daten, ENABLE NOVALIDATE, dann validiert, mit einer Warnung bei verwaisten Zeilen

    Der Schlüssel prüft neue Zeilen sofort und wird zuletzt validiert; Zeilen ohne Elternzeile lassen ihn mit einer Warnung unvalidiert, statt das Laden abzubrechen.

  • ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT

    entfernt

    Fremdschlüssel in Oracle handeln nur beim Löschen, mit CASCADE oder SET NULL.

    Berichtszeile: foreign_key_action_unsupported

  • foreign keys to tables the dump doesn't create

    nicht angelegt

    Ein Schlüssel kann nicht auf eine Tabelle verweisen, die es nicht gibt.

    Berichtszeile: foreign_key_skipped

  • names over 128 bytes

    gekürzt

    Namen fassen in Oracle 12.2 und neuer 128 Bytes, mehr als die 63 von PostgreSQL.

    Berichtszeile: name_shortened

  • partitioned tables

    eine Tabelle mit den Zeilen aller Partitionen

    Die Zeilen sind dieselben; partitioniere die Tabelle in Oracle neu, wenn nötig.

    Berichtszeile: partitions_dropped

  • schemas

    ein Schema, jede Tabelle mit dem Namen ihres Schemas vorangestellt

    Das Skript lädt in das Schema des ausführenden Benutzers, daher bekommen Tabellen verschiedener Schemas den Namen ihres Schemas vorangestellt; Tabellen in public behalten ihre Namen.

    Berichtszeile: schemas_merged

  • views, functions, procedures, triggers, rules, policies, extensions and types

    im Bericht aufgeführt

    Ihr Code ist in der Sprache von PostgreSQL geschrieben, daher werden sie aufgeführt, damit du sie neu anlegst.

    Berichtszeile: not_converted_objects

  • dumps without CREATE TABLE (--data-only)

    Typen aus den Werten gelesen

    Ein Dump nur mit Daten enthält nur Zeilen, daher kommen die Typen aus den Werten.

    Berichtszeile: no_schema

  • expressions in INSERT values

    NULL

    Ein Konverter, der keine Datenbank ausführt, kann sie nicht auswerten.

    Berichtszeile: expression_value

  • types IntoSQL doesn't know

    CLOB

    Text nimmt jeden Wert auf; ändere den Typ nach dem Laden.

    Berichtszeile: unknown_type

  • text that isn't valid in its encoding

    die fehlerhaften Bytes als Ersatzzeichen

    Das Skript ist UTF-8 und lädt mit NLS_LANG=.AL32UTF8.

    Berichtszeile: invalid_utf8_replaced

  • text decoded twice (ñ)

    unverändert kopiert

    Der Dump enthält genau diese Zeichen, daher werden sie kopiert; der Bericht weist auf sie hin.

    Berichtszeile: mojibake_suspected

In PostgreSQLIn OracleBerichtszeile
booleanNUMBER(1) mit einem CHECK auf 0 und 1Oracle 21c hat keinen booleschen Spaltentyp; 1 und 0 bewahren true und false auf jeder Version.
varchar(n), char(n)VARCHAR2(n CHAR), in Zeichen gezähltLängen zählen Zeichen wie in PostgreSQL.
textVARCHAR2(4000 CHAR), wenn jeder Wert in 4000 Bytes passt (750 Zeichen in einem Schlüssel), sonst CLOBEin VARCHAR2 fasst standardmäßig 4000 Bytes, und Oracle kann kein CLOB indizieren, daher behält Text VARCHAR2, wenn seine Werte passen, und wird sonst ein CLOB.text_as_lob
empty strings and empty bytea valuesNULLOracle speichert einen leeren String als NULL, daher wird ein Wert, der ' war, als NULL gelesen. Der Bericht zählt sie pro Spalte.empty_string_null
citextexakter VergleichOracle vergleicht Text exakt, sofern nicht anders angegeben, wie text in PostgreSQL; citext-Spalten vergleichen nicht mehr ohne Groß-/Kleinschreibung.case_insensitive_collation
numeric(p,s) past 38 digits; numeric without a precisionNUMBER, wenn seine Werte in 38 Stellen passen, sonst VARCHAR2NUMBER in Oracle fasst 38 Stellen bei jeder Skalierung. Breitere Zahlen bleiben Text, damit jede Stelle exakt bleibt.decimal_as_text
moneyNUMBER(19,2)Oracle hat keinen money-Typ. Der Betrag bleibt eine Zahl, ohne das Währungssymbol, das die Locale des Servers hinzugefügt hat.type_replaced
intervalVARCHAR2(100 CHAR) mit dem Text von PostgreSQLEin interval mischt Monate mit Tagen und Sekunden, die Oracle in zwei verschiedenen Typen hält; der Text behält jeden Teil.type_replaced
arrays (integer[], text[]...)CLOB mit einem JSON-ArrayOracle hat keine Arrays. Ein JSON-Array behält jedes Element und NULL, und JSON_TABLE liest es.type_replaced
ranges, geometric types, tsvector, xml, hstore, PostGIS, composite and extension typesVARCHAR2 oder CLOB mit dem Text von PostgreSQLOracle hat keinen entsprechenden Typ, daher behält jeder Wert den Text, den PostgreSQL geschrieben hat.type_replaced
json, jsonbCLOBDie JSON-Funktionen von Oracle lesen JSON auf jeder Version aus Text, und ein CLOB fasst Werte jeder Größe.
timestampTIMESTAMPEin timestamp without time zone ist eine Uhrzeitangabe ohne Zeitzone, wie TIMESTAMP in Oracle. date wird DATE, das auch eine Uhrzeit enthält, die auf Mitternacht bleibt.
timestamp with time zoneTIMESTAMP WITH TIME ZONE in UTCJeder Wert wird in UTC geschrieben: derselbe Zeitpunkt, welchen Versatz der Dump auch geschrieben hat.
timeINTERVAL DAY TO SECOND ab MitternachtOracle hat keinen Uhrzeittyp; ein Intervall ab Mitternacht fasst jeden Wert, einschließlich 24:00:00.
infinity, -infinity, BC dates and years past 9999NULLDas Skript schreibt die Jahre 1 bis 9999, und Oracle kennt kein Unendlich. Diese Werte werden NULL, und der Bericht zählt sie.date_out_of_range
NaN and Infinity in numericNULLNUMBER in Oracle kennt weder NaN noch Infinity, daher werden diese Werte NULL, und der Bericht zählt sie.invalid_value_null
NOT NULL columns with values that become NULLNOT NULL entferntEine Spalte, deren Werte NULL werden mussten, kann NOT NULL nicht behalten, sonst würde das Laden abbrechen.not_null_relaxed
enum typesVARCHAR2 mit einem CHECK seiner LabelsText mit einer CHECK-Bedingung behält dieselben Werte.
enum columns holding values outside their labelsVARCHAR2 ohne CHECKWerte, die nicht unter den Labels stehen, würden die CHECK-Bedingung verletzen, daher wird sie nicht angelegt.enum_check_skipped
uuid, inet, cidr, macaddrVARCHAR2Oracle hat solche Typen nicht; der Text behält jeden Wert.
byteaBLOBBytes bleiben Bytes.
bit(n), bit varyingNUMBER mit dem Wert der Bits bis 63 Bit; darüber Ziffern als TextBitstrings werden als die Zahl gespeichert, die ihre Bits ergeben.
oid, xid, cidNUMBER(10) mit einem CHECK gegen negative WerteNUMBER fasst jeden Wert.
serial, identityGENERATED BY DEFAULT ON NULL AS IDENTITY, weiter nach der höchsten IDDie kopierten IDs laden unverändert, und der Zähler macht nach der höchsten weiter oder beim nächsten Wert der Sequenz, je nachdem, was höher ist.
a second serial or identity column in a tableeine normale GanzzahlOracle zählt eine Identity-Spalte pro Tabelle; jede andere behält ihre Werte ohne Zähler.counter_dropped
sequences not owned by a columnCREATE SEQUENCE, bei dem Wert, den sie erreicht hatteSequenzen in Oracle funktionieren genauso.
generated columnsvirtuelle SpaltenOracle berechnet generierte Spalten nur beim Lesen; STORED-Spalten werden virtuell, mit denselben Werten.stored_as_virtual
generated columns with functions Oracle lackseine normale Spalte mit den WertenEine Formel, die sich nicht für Oracle schreiben lässt, hinterlässt eine normale Spalte mit den Werten des Dumps und eine Zeile im Bericht.generated_not_translated
defaults with functions Oracle lacks, and defaults from a sequencekein StandardwertEin Standardwert, der sich nicht für Oracle schreiben lässt, wird weggelassen und gemeldet.default_not_translated
CHECK constraintsübersetzt, inline in CREATE TABLEInline-CHECK-Bedingungen werden beim Laden jeder Zeile geprüft.
CHECK constraints with functions Oracle lacksnicht angelegtEine CHECK-Bedingung, die sich nicht für Oracle schreiben lässt, wird weggelassen und gemeldet.check_skipped
CHECK ... NOT VALIDnicht angelegtPostgreSQL hat die vorher vorhandenen Zeilen nie geprüft, daher können sie die CHECK-Bedingung verletzen.check_not_valid
gin, gist, brin and hash indexes, partial and expression indexes, and indexes on CLOB columnsnicht angelegtIntoSQL schreibt für Oracle B-Tree-Indizes auf Spalten, und Oracle kann kein CLOB indizieren; lege die anderen nach dem Laden neu an.index_skipped
foreign keysnach den Daten, ENABLE NOVALIDATE, dann validiert, mit einer Warnung bei verwaisten ZeilenDer Schlüssel prüft neue Zeilen sofort und wird zuletzt validiert; Zeilen ohne Elternzeile lassen ihn mit einer Warnung unvalidiert, statt das Laden abzubrechen.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULTentferntFremdschlüssel in Oracle handeln nur beim Löschen, mit CASCADE oder SET NULL.foreign_key_action_unsupported
foreign keys to tables the dump doesn't createnicht angelegtEin Schlüssel kann nicht auf eine Tabelle verweisen, die es nicht gibt.foreign_key_skipped
names over 128 bytesgekürztNamen fassen in Oracle 12.2 und neuer 128 Bytes, mehr als die 63 von PostgreSQL.name_shortened
partitioned tableseine Tabelle mit den Zeilen aller PartitionenDie Zeilen sind dieselben; partitioniere die Tabelle in Oracle neu, wenn nötig.partitions_dropped
schemasein Schema, jede Tabelle mit dem Namen ihres Schemas vorangestelltDas Skript lädt in das Schema des ausführenden Benutzers, daher bekommen Tabellen verschiedener Schemas den Namen ihres Schemas vorangestellt; Tabellen in public behalten ihre Namen.schemas_merged
views, functions, procedures, triggers, rules, policies, extensions and typesim Bericht aufgeführtIhr Code ist in der Sprache von PostgreSQL geschrieben, daher werden sie aufgeführt, damit du sie neu anlegst.not_converted_objects
dumps without CREATE TABLE (--data-only)Typen aus den Werten gelesenEin Dump nur mit Daten enthält nur Zeilen, daher kommen die Typen aus den Werten.no_schema
expressions in INSERT valuesNULLEin Konverter, der keine Datenbank ausführt, kann sie nicht auswerten.expression_value
types IntoSQL doesn't knowCLOBText nimmt jeden Wert auf; ändere den Typ nach dem Laden.unknown_type
text that isn't valid in its encodingdie fehlerhaften Bytes als ErsatzzeichenDas Skript ist UTF-8 und lädt mit NLS_LANG=.AL32UTF8.invalid_utf8_replaced
text decoded twice (ñ)unverändert kopiertDer Dump enthält genau diese Zeichen, daher werden sie kopiert; der Bericht weist auf sie hin.mojibake_suspected

Das Skript in Oracle laden

Das Skript legt die Tabellen an, kopiert die Zeilen und fügt dann Schlüssel, Indizes und Fremdschlüssel hinzu, so lädt es schnell und hält beim ersten Fehler an.

NLS_LANG=.AL32UTF8 sqlplus -S -L user@//localhost/mydb @postgresql.oracle.sql

Fremdschlüssel werden mit ENABLE NOVALIDATE hinzugefügt, sodass neue Zeilen sofort geprüft werden, und dann validiert. Verweist eine alte Zeile auf eine nicht vorhandene Zeile, nennt das Skript den Fremdschlüssel und lässt ihn unvalidiert, statt auf halbem Weg abzubrechen.

Führe bei einem großen Dump SQL*Plus auf dem Rechner der Datenbank aus. Das Skript schreibt alle 100 Zeilen fest. Der ausführende Benutzer braucht CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER und CREATE PROCEDURE sowie Quota auf seinem Tablespace.

Den PostgreSQL-Dump für das beste Ergebnis erstellen

Der Konverter liest, was der Dump enthält. Mit diesen Optionen bleibt mehr von deinen Daten darin:

  • --format=plain, die Standardeinstellung von pg_dump, schreibt SQL. Ein custom- oder directory-Archiv (-Fc, -Fd) wird mit pg_restore -f dump.sql zu SQL, ohne Datenbankserver.
  • --no-owner --no-privileges lassen Rollen und Rechte weg, die der Konverter ohnehin überspringt, daher wird der Dump kleiner.
  • pg_dumpall schreibt jede Datenbank in eine Datei; die Tabellen jeder Datenbank werden nach ihr benannt, damit nichts kollidiert.

Was nicht konvertiert wird

Sichten, materialisierte Sichten, Funktionen, Prozeduren, Trigger, Regeln, Zeilensicherheitsrichtlinien, Erweiterungen und Typen sind in der eigenen Sprache von PostgreSQL geschrieben. Sie stehen mit Namen im Bericht und werden nie stillschweigend weggelassen, damit du sie für Oracle neu schreiben kannst.

Fragen zu PostgreSQL zu Oracle

Keine Antwort gefunden? Schreib uns über die Kontaktseite, und ein Mensch antwortet. Kontaktseite

Wird mein Dump hochgeladen?

Nein. Der Konverter läuft in deinem Browser und liest den Dump stückweise von deiner Festplatte, daher verlässt er nie deinen Computer. Die Desktop-App und die Kommandozeile konvertieren ebenfalls auf deinem Computer.

Wie groß darf der Dump sein?

Der Konverter hält nie den ganzen Dump im Speicher: Er liest die Datei zweimal, in Abschnitten, und schreibt das Skript fortlaufend. Dumps von mehreren Gigabyte werden im Browser, in der Desktop-App und mit der Kommandozeile konvertiert.

Liest es pg_dump -Fc-Archive?

Nicht direkt: Ein custom-Archiv ist ein Binärformat. pg_restore -f dump.sql dump.backup wandelt es in das einfache SQL um, das der Konverter liest, ohne Verbindung zu einem Server. Der Konverter sagt das, wenn er ein Archiv bekommt.

Aus welchen PostgreSQL-Versionen kann der Dump stammen?

Dumps aus pg_dump und pg_dumpall ab PostgreSQL 10, mit COPY- oder INSERT-Zeilen. Jeder Test-Dump stammt aus PostgreSQL 13 und 18 und wird Zelle für Zelle mit seiner Quelle verglichen.

Bleiben serial- und Identity-Werte erhalten?

Ja. Die serial- oder Identity-Spalte jeder Tabelle wird eine Identity-Spalte, jede Zeile behält ihre ID, und die nächste ID macht nach der höchsten weiter. Sequenzen, die keiner Spalte gehören, werden Oracle-Sequenzen bei dem Wert, den sie erreicht hatten.

Was passiert mit Arrays, enums und anderen PostgreSQL-Typen?

Arrays werden JSON-Arrays, Booleans NUMBER(1), Zeitstempel mit Zeitzone TIMESTAMP WITH TIME ZONE und Text VARCHAR2, wenn seine Werte passen, sonst CLOB. Leere Strings werden NULL, wie Oracle sie speichert, und der Bericht zählt sie.

Was ist mit Funktionen, Triggern und Sichten?

Sie stehen mit Namen im Bericht und werden nicht konvertiert, weil jede Datenbank sie in ihrer eigenen Sprache schreibt.

Auf welchen Oracle-Versionen lädt das Skript?

Oracle 19c und neuer. Jeder Test-Dump lädt auf 21c und 23ai und hält beim ersten Fehler an, falls etwas schiefgeht.