Saltar al contenido
Inicio de IntoSQL

Convierte PostgreSQL a Oracle

Suelta un volcado plano de pg_dump o pg_dumpall, en .sql o .sql.gz, y descarga un script de Oracle con las mismas tablas, claves, índices y datos. Cada valor que Oracle no puede guardar tal cual, y cada objeto que no admite, aparece en el informe.

Tu archivo
sqlshop_2024_postgres.sqlArchivo de ejemplo, 6,2 kB
Tu base de datos

18 filas convertidas, 2 correcciones, ninguna rechazada

Mostrar

Tablas en shop_2024_postgres.sqlVolcado de PostgreSQL 18.6 · escrito por pg_dump · utf8mb4

  • customersescrita como CUSTOMERS8 filas1
    8 columnas
    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
  • ordersescrita como ORDERS10 filas1
    10 columnas
    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)

Sin convertir

  • Vista paid_orders

Cada base de datos los escribe en su propio lenguaje. Reescríbelos para 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;

Correcciones

  1. "tags" de customers es text[], que Oracle no tiene, así que es CLOB con los mismos valores.
  2. "delivery" de orders es interval, que Oracle no tiene, así que es VARCHAR2(100 CHAR) con los mismos valores.

Para revisar

  • 1 vista, disparador, rutina o evento no se convierte; el informe lista cada uno. Vuelve a crearlos a mano en Oracle.
  • El valor predeterminado de "tags" en customers no se puede escribir para Oracle (a value its type can't hold), así que la columna no tiene valor predeterminado. Agrega el valor predeterminado a mano si las filas nuevas lo necesitan.
  • El índice idx_orders_details de orders usa una expresión que no se puede escribir para Oracle (a gin index), así que no se crea. Crea el índice a mano si las consultas lo necesitan.
  • 1 valor en "shipped_at" de orders es una fecha que Oracle no puede guardar, como infinity, así que queda en NULL. Oracle guarda los años 1 a 9999 sin infinito; reemplaza esas fechas en el origen si importan.

Tu archivo se convierte en esta computadora y nunca se sube.

Otros ejemplos:

Qué cambia de PostgreSQL a Oracle

Cada fila es una regla que aplica el convertidor, con la línea que escribe en el informe cuando la regla cambia algo en tus datos.

  • boolean

    NUMBER(1) con un CHECK de 0 y 1

    Oracle 21c no tiene un tipo de columna booleano; 1 y 0 conservan true y false en cada versión.

  • varchar(n), char(n)

    VARCHAR2(n CHAR), contando caracteres

    Las longitudes cuentan caracteres, como las de PostgreSQL.

  • text

    VARCHAR2(4000 CHAR) cuando cada valor cabe en 4000 bytes (750 caracteres en una clave), si no CLOB

    Un VARCHAR2 admite 4000 bytes por defecto y Oracle no puede indexar un CLOB, así que el texto se queda en VARCHAR2 cuando sus valores caben y es un CLOB cuando no.

    Línea del informe: text_as_lob

  • empty strings and empty bytea values

    NULL

    Oracle guarda una cadena vacía como NULL, así que un valor que era ' se lee como NULL. El informe los cuenta por columna.

    Línea del informe: empty_string_null

  • citext

    comparación exacta

    Oracle compara el texto exactamente salvo que se indique otra cosa, como el text de PostgreSQL; las columnas citext dejan de ignorar mayúsculas.

    Línea del informe: case_insensitive_collation

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

    NUMBER cuando sus valores caben en 38 dígitos, si no VARCHAR2

    El NUMBER de Oracle admite 38 dígitos en cualquier escala. Los números más anchos se guardan como texto para que cada dígito siga exacto.

    Línea del informe: decimal_as_text

  • money

    NUMBER(19,2)

    Oracle no tiene tipo money. El importe se guarda como número, sin el símbolo de moneda que agregó la configuración regional del servidor.

    Línea del informe: type_replaced

  • interval

    VARCHAR2(100 CHAR) con el texto de PostgreSQL

    Un interval mezcla meses con días y segundos, que Oracle guarda en dos tipos distintos; el texto conserva cada parte.

    Línea del informe: type_replaced

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

    CLOB con un arreglo JSON

    Oracle no tiene arreglos. Un arreglo JSON conserva cada elemento y NULL, y JSON_TABLE lo lee.

    Línea del informe: type_replaced

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

    VARCHAR2 o CLOB con el texto de PostgreSQL

    Oracle no tiene un tipo equivalente, así que cada valor conserva el texto que escribió PostgreSQL.

    Línea del informe: type_replaced

  • json, jsonb

    CLOB

    Las funciones JSON de Oracle leen JSON desde texto en cada versión, y un CLOB conserva valores de cualquier tamaño.

  • timestamp

    TIMESTAMP

    Un timestamp sin zona horaria es una lectura de reloj, como el TIMESTAMP de Oracle. date se vuelve DATE, que también guarda una hora del día que se queda en medianoche.

  • timestamp with time zone

    TIMESTAMP WITH TIME ZONE en UTC

    Cada valor se escribe en UTC, el mismo instante sea cual sea el desfase que escribió el volcado.

  • time

    INTERVAL DAY TO SECOND desde la medianoche

    Oracle no tiene un tipo para la hora del día; un intervalo desde medianoche admite cada valor, 24:00:00 incluido.

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

    NULL

    El script escribe los años 1 a 9999, y Oracle no tiene infinito. Esos valores se vuelven NULL y el informe los cuenta.

    Línea del informe: date_out_of_range

  • NaN and Infinity in numeric

    NULL

    El NUMBER de Oracle no tiene NaN ni Infinity, así que esos valores se vuelven NULL y el informe los cuenta.

    Línea del informe: invalid_value_null

  • NOT NULL columns with values that become NULL

    sin NOT NULL

    Una columna cuyos valores tuvieron que volverse NULL no puede conservar NOT NULL, o la carga se detendría.

    Línea del informe: not_null_relaxed

  • enum types

    VARCHAR2 con un CHECK de sus etiquetas

    El texto con un CHECK conserva los mismos valores.

  • enum columns holding values outside their labels

    VARCHAR2 sin CHECK

    Los valores que las etiquetas no nombran no cumplirían el CHECK, así que el CHECK no se crea.

    Línea del informe: enum_check_skipped

  • uuid, inet, cidr, macaddr

    VARCHAR2

    Oracle no tiene esos tipos; el texto conserva cada valor.

  • bytea

    BLOB

    Los bytes siguen siendo bytes.

  • bit(n), bit varying

    NUMBER con el valor de los bits hasta 63 bits; dígitos en texto si son más

    Las cadenas de bits se guardan como el número que forman sus bits.

  • oid, xid, cid

    NUMBER(10) con un CHECK de que no sea negativo

    NUMBER admite cada valor.

  • serial, identity

    GENERATED BY DEFAULT ON NULL AS IDENTITY, siguiendo después del id más alto

    Los ids copiados se cargan tal cual, y el contador sigue después del más alto o del siguiente valor de la secuencia, el que sea mayor.

  • a second serial or identity column in a table

    un entero simple

    Oracle cuenta una columna de identidad por tabla; cualquier otra conserva sus valores sin contador.

    Línea del informe: counter_dropped

  • sequences not owned by a column

    CREATE SEQUENCE, en el valor que había alcanzado

    Las secuencias de Oracle funcionan de la misma forma.

  • generated columns

    columnas virtuales

    Oracle solo calcula las columnas generadas al leer; las columnas STORED se vuelven virtuales con los mismos valores.

    Línea del informe: stored_as_virtual

  • generated columns with functions Oracle lacks

    una columna simple con los valores

    Una fórmula que no se puede escribir para Oracle deja una columna simple con los valores del volcado y una línea en el informe.

    Línea del informe: generated_not_translated

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

    sin valor predeterminado

    Un valor predeterminado que no se puede escribir para Oracle se deja fuera y aparece en el informe.

    Línea del informe: default_not_translated

  • CHECK constraints

    traducido, en línea en CREATE TABLE

    Los CHECK en línea se comprueban al cargar cada fila.

  • CHECK constraints with functions Oracle lacks

    no se crea

    Un CHECK que no se puede escribir para Oracle se deja fuera y aparece en el informe.

    Línea del informe: check_skipped

  • CHECK ... NOT VALID

    no se crea

    PostgreSQL nunca comprobó las filas que ya estaban, así que pueden no cumplirlo.

    Línea del informe: check_not_valid

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

    no se crea

    IntoSQL escribe índices b-tree sobre columnas para Oracle, que no puede indexar un CLOB; vuelve a crear los demás después de cargar.

    Línea del informe: index_skipped

  • foreign keys

    después de los datos, ENABLE NOVALIDATE, luego validada con una advertencia si hay huérfanas

    La clave comprueba las filas nuevas de inmediato y se valida al final; las filas sin padre la dejan sin validar con una advertencia en lugar de detener la carga.

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

    se descarta

    Las claves foráneas de Oracle solo actúan al eliminar, con CASCADE o SET NULL.

    Línea del informe: foreign_key_action_unsupported

  • foreign keys to tables the dump doesn't create

    no se crea

    Una clave no puede nombrar una tabla que no existe.

    Línea del informe: foreign_key_skipped

  • names over 128 bytes

    acortado

    Los nombres de Oracle 12.2 y posteriores admiten 128 bytes, más que los 63 de PostgreSQL.

    Línea del informe: name_shortened

  • partitioned tables

    una tabla con las filas de todas las particiones

    Las filas son las mismas; vuelve a particionar la tabla en Oracle si lo necesita.

    Línea del informe: partitions_dropped

  • schemas

    un esquema, con el nombre del esquema delante de cada tabla

    El script carga en el esquema del usuario que lo ejecuta, así que las tablas de distintos esquemas llevan delante el nombre de su esquema; las tablas de public conservan sus nombres.

    Línea del informe: schemas_merged

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

    listados en el informe

    Su código está escrito en el lenguaje de PostgreSQL, así que se listan para que los vuelvas a crear.

    Línea del informe: not_converted_objects

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

    tipos leídos de los valores

    Un volcado solo de datos solo tiene filas, así que los tipos salen de los valores.

    Línea del informe: no_schema

  • expressions in INSERT values

    NULL

    Un convertidor que no ejecuta una base de datos no puede evaluarlas.

    Línea del informe: expression_value

  • types IntoSQL doesn't know

    CLOB

    El texto admite cualquier valor; cambia el tipo después de cargar.

    Línea del informe: unknown_type

  • text that isn't valid in its encoding

    los bytes incorrectos como carácter de reemplazo

    El script es UTF-8 y carga con NLS_LANG=.AL32UTF8.

    Línea del informe: invalid_utf8_replaced

  • text decoded twice (ñ)

    se copia tal cual

    El volcado contiene exactamente estos caracteres, así que se copian; el informe los señala.

    Línea del informe: mojibake_suspected

En PostgreSQLEn OracleLínea del informe
booleanNUMBER(1) con un CHECK de 0 y 1Oracle 21c no tiene un tipo de columna booleano; 1 y 0 conservan true y false en cada versión.
varchar(n), char(n)VARCHAR2(n CHAR), contando caracteresLas longitudes cuentan caracteres, como las de PostgreSQL.
textVARCHAR2(4000 CHAR) cuando cada valor cabe en 4000 bytes (750 caracteres en una clave), si no CLOBUn VARCHAR2 admite 4000 bytes por defecto y Oracle no puede indexar un CLOB, así que el texto se queda en VARCHAR2 cuando sus valores caben y es un CLOB cuando no.text_as_lob
empty strings and empty bytea valuesNULLOracle guarda una cadena vacía como NULL, así que un valor que era ' se lee como NULL. El informe los cuenta por columna.empty_string_null
citextcomparación exactaOracle compara el texto exactamente salvo que se indique otra cosa, como el text de PostgreSQL; las columnas citext dejan de ignorar mayúsculas.case_insensitive_collation
numeric(p,s) past 38 digits; numeric without a precisionNUMBER cuando sus valores caben en 38 dígitos, si no VARCHAR2El NUMBER de Oracle admite 38 dígitos en cualquier escala. Los números más anchos se guardan como texto para que cada dígito siga exacto.decimal_as_text
moneyNUMBER(19,2)Oracle no tiene tipo money. El importe se guarda como número, sin el símbolo de moneda que agregó la configuración regional del servidor.type_replaced
intervalVARCHAR2(100 CHAR) con el texto de PostgreSQLUn interval mezcla meses con días y segundos, que Oracle guarda en dos tipos distintos; el texto conserva cada parte.type_replaced
arrays (integer[], text[]...)CLOB con un arreglo JSONOracle no tiene arreglos. Un arreglo JSON conserva cada elemento y NULL, y JSON_TABLE lo lee.type_replaced
ranges, geometric types, tsvector, xml, hstore, PostGIS, composite and extension typesVARCHAR2 o CLOB con el texto de PostgreSQLOracle no tiene un tipo equivalente, así que cada valor conserva el texto que escribió PostgreSQL.type_replaced
json, jsonbCLOBLas funciones JSON de Oracle leen JSON desde texto en cada versión, y un CLOB conserva valores de cualquier tamaño.
timestampTIMESTAMPUn timestamp sin zona horaria es una lectura de reloj, como el TIMESTAMP de Oracle. date se vuelve DATE, que también guarda una hora del día que se queda en medianoche.
timestamp with time zoneTIMESTAMP WITH TIME ZONE en UTCCada valor se escribe en UTC, el mismo instante sea cual sea el desfase que escribió el volcado.
timeINTERVAL DAY TO SECOND desde la medianocheOracle no tiene un tipo para la hora del día; un intervalo desde medianoche admite cada valor, 24:00:00 incluido.
infinity, -infinity, BC dates and years past 9999NULLEl script escribe los años 1 a 9999, y Oracle no tiene infinito. Esos valores se vuelven NULL y el informe los cuenta.date_out_of_range
NaN and Infinity in numericNULLEl NUMBER de Oracle no tiene NaN ni Infinity, así que esos valores se vuelven NULL y el informe los cuenta.invalid_value_null
NOT NULL columns with values that become NULLsin NOT NULLUna columna cuyos valores tuvieron que volverse NULL no puede conservar NOT NULL, o la carga se detendría.not_null_relaxed
enum typesVARCHAR2 con un CHECK de sus etiquetasEl texto con un CHECK conserva los mismos valores.
enum columns holding values outside their labelsVARCHAR2 sin CHECKLos valores que las etiquetas no nombran no cumplirían el CHECK, así que el CHECK no se crea.enum_check_skipped
uuid, inet, cidr, macaddrVARCHAR2Oracle no tiene esos tipos; el texto conserva cada valor.
byteaBLOBLos bytes siguen siendo bytes.
bit(n), bit varyingNUMBER con el valor de los bits hasta 63 bits; dígitos en texto si son másLas cadenas de bits se guardan como el número que forman sus bits.
oid, xid, cidNUMBER(10) con un CHECK de que no sea negativoNUMBER admite cada valor.
serial, identityGENERATED BY DEFAULT ON NULL AS IDENTITY, siguiendo después del id más altoLos ids copiados se cargan tal cual, y el contador sigue después del más alto o del siguiente valor de la secuencia, el que sea mayor.
a second serial or identity column in a tableun entero simpleOracle cuenta una columna de identidad por tabla; cualquier otra conserva sus valores sin contador.counter_dropped
sequences not owned by a columnCREATE SEQUENCE, en el valor que había alcanzadoLas secuencias de Oracle funcionan de la misma forma.
generated columnscolumnas virtualesOracle solo calcula las columnas generadas al leer; las columnas STORED se vuelven virtuales con los mismos valores.stored_as_virtual
generated columns with functions Oracle lacksuna columna simple con los valoresUna fórmula que no se puede escribir para Oracle deja una columna simple con los valores del volcado y una línea en el informe.generated_not_translated
defaults with functions Oracle lacks, and defaults from a sequencesin valor predeterminadoUn valor predeterminado que no se puede escribir para Oracle se deja fuera y aparece en el informe.default_not_translated
CHECK constraintstraducido, en línea en CREATE TABLELos CHECK en línea se comprueban al cargar cada fila.
CHECK constraints with functions Oracle lacksno se creaUn CHECK que no se puede escribir para Oracle se deja fuera y aparece en el informe.check_skipped
CHECK ... NOT VALIDno se creaPostgreSQL nunca comprobó las filas que ya estaban, así que pueden no cumplirlo.check_not_valid
gin, gist, brin and hash indexes, partial and expression indexes, and indexes on CLOB columnsno se creaIntoSQL escribe índices b-tree sobre columnas para Oracle, que no puede indexar un CLOB; vuelve a crear los demás después de cargar.index_skipped
foreign keysdespués de los datos, ENABLE NOVALIDATE, luego validada con una advertencia si hay huérfanasLa clave comprueba las filas nuevas de inmediato y se valida al final; las filas sin padre la dejan sin validar con una advertencia en lugar de detener la carga.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULTse descartaLas claves foráneas de Oracle solo actúan al eliminar, con CASCADE o SET NULL.foreign_key_action_unsupported
foreign keys to tables the dump doesn't createno se creaUna clave no puede nombrar una tabla que no existe.foreign_key_skipped
names over 128 bytesacortadoLos nombres de Oracle 12.2 y posteriores admiten 128 bytes, más que los 63 de PostgreSQL.name_shortened
partitioned tablesuna tabla con las filas de todas las particionesLas filas son las mismas; vuelve a particionar la tabla en Oracle si lo necesita.partitions_dropped
schemasun esquema, con el nombre del esquema delante de cada tablaEl script carga en el esquema del usuario que lo ejecuta, así que las tablas de distintos esquemas llevan delante el nombre de su esquema; las tablas de public conservan sus nombres.schemas_merged
views, functions, procedures, triggers, rules, policies, extensions and typeslistados en el informeSu código está escrito en el lenguaje de PostgreSQL, así que se listan para que los vuelvas a crear.not_converted_objects
dumps without CREATE TABLE (--data-only)tipos leídos de los valoresUn volcado solo de datos solo tiene filas, así que los tipos salen de los valores.no_schema
expressions in INSERT valuesNULLUn convertidor que no ejecuta una base de datos no puede evaluarlas.expression_value
types IntoSQL doesn't knowCLOBEl texto admite cualquier valor; cambia el tipo después de cargar.unknown_type
text that isn't valid in its encodinglos bytes incorrectos como carácter de reemplazoEl script es UTF-8 y carga con NLS_LANG=.AL32UTF8.invalid_utf8_replaced
text decoded twice (ñ)se copia tal cualEl volcado contiene exactamente estos caracteres, así que se copian; el informe los señala.mojibake_suspected

Carga el script en Oracle

El script crea las tablas, copia las filas y luego agrega claves, índices y claves foráneas, así que carga rápido y se detiene en el primer error.

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

Las claves foráneas se agregan ENABLE NOVALIDATE, así que las filas nuevas se comprueban de inmediato, y luego se validan. Si una fila antigua apunta a una fila que no existe, el script dice qué restricción es y la deja sin validar, en lugar de fallar a medias.

Para un volcado grande, ejecuta SQL*Plus en la misma máquina que la base de datos. El script confirma cada 100 filas. El usuario que lo ejecuta necesita CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER y CREATE PROCEDURE, y cuota en su tablespace.

Haz el volcado de PostgreSQL para el mejor resultado

El convertidor lee lo que contiene el volcado. Estas opciones conservan más de tus datos en él:

  • --format=plain, el formato predeterminado de pg_dump, escribe SQL. Un archivo custom o de directorio (-Fc, -Fd) pasa a SQL con pg_restore -f dump.sql, sin un servidor de base de datos.
  • --no-owner --no-privileges dejan fuera los roles y los permisos, que el convertidor omite de todos modos, así que el volcado es más pequeño.
  • pg_dumpall vuelca todas las bases de datos en un archivo; las tablas de cada una llevan su nombre, así que nada choca.

Qué no se convierte

Las vistas, vistas materializadas, funciones, procedimientos, disparadores, reglas, políticas de seguridad de filas, extensiones y tipos se escriben en el lenguaje propio de PostgreSQL. Aparecen en el informe por nombre, nunca se descartan en silencio, para que puedas reescribirlos para Oracle.

Preguntas sobre PostgreSQL a Oracle

¿No encuentras la respuesta? Escríbenos desde la página de contacto y te responde una persona. Página de contacto

¿Se sube mi volcado?

No. El convertidor se ejecuta en tu navegador y lee el volcado de tu disco por partes, así que nunca sale de tu computadora. La app de escritorio y la línea de comandos también convierten en tu computadora.

¿Qué tan grande puede ser el volcado?

El convertidor nunca tiene todo el volcado en memoria: lee el archivo dos veces, por rangos, y escribe el script sobre la marcha. Los volcados de varios gigabytes se convierten en el navegador, en la app de escritorio y con la línea de comandos.

¿Lee archivos de pg_dump -Fc?

No directamente: un archivo custom tiene formato binario. pg_restore -f dump.sql dump.backup lo pasa al SQL plano que lee el convertidor, sin conectarse a un servidor. El convertidor lo indica cuando recibe un archivo así.

¿De qué versiones de PostgreSQL puede venir el volcado?

Volcados escritos por pg_dump y pg_dumpall de PostgreSQL 10 en adelante, con filas COPY o INSERT. Cada volcado de prueba viene de PostgreSQL 13 y 18 y se compara con su origen celda por celda.

¿Se conservan los valores serial e identity?

Sí. La columna serial o identity de cada tabla se vuelve una columna de identidad, cada fila conserva su id y el siguiente id sigue después del más alto. Las secuencias que no pertenecen a una columna se vuelven secuencias de Oracle en el valor que habían alcanzado.

¿Qué pasa con los arreglos, los enum y otros tipos de PostgreSQL?

Los arreglos se vuelven arreglos JSON, los booleanos NUMBER(1), los timestamps con zona horaria TIMESTAMP WITH TIME ZONE, y el texto VARCHAR2 cuando sus valores caben, si no CLOB. Las cadenas vacías se vuelven NULL, como las guarda Oracle, y el informe las cuenta.

¿Qué pasa con las funciones, los disparadores y las vistas?

Aparecen en el informe por nombre y no se convierten, porque cada base de datos los escribe en su propio lenguaje.

¿En qué versiones de Oracle carga el script?

Oracle 19c y posteriores. Cada volcado de prueba carga en 21c y 23ai, y se detiene en el primer error si algo sale mal.