Pular para o conteúdo
Início do IntoSQL

Converta Oracle para PostgreSQL

Solte o arquivo .sql que o Database Export do SQL Developer ou o SQLcl escreve, com suas tabelas e instruções Insert, e baixe um script do PostgreSQL com as mesmas tabelas, chaves, índices e dados. Cada valor que o PostgreSQL não aceita como está, e cada objeto que ele não traz, aparece no relatório.

Seu arquivo
sqlshop_2024_oracle.sqlArquivo de exemplo, 9,3 kB
Seu banco de dados

18 linhas convertidas, nenhuma correção, nenhuma rejeitada

Mostrar

Tabelas em shop_2024_oracle.sqlDump do Oracle · gerado por SQL Developer · utf-8

  • customers8 linhas
    7 colunas
    idbigint not null
    namevarchar(100) not null
    emailvarchar(150) not null
    countryvarchar(2) not null
    is_activesmallint not null
    signed_uptimestamp(0)
    created_attimestamp(0) not null
  • orders10 linhas
    9 colunas
    idbigint not null
    customer_idbigint not null
    invoicebigint
    statusvarchar(10) not null
    totalnumeric(10,2) not null
    itemsinteger not null
    ordered_attimestamp(0) not null
    shipped_attimestamp(0)
    notevarchar(255)
-- Written by IntoSQL from a Oracle dump. Load it with: psql -v ON_ERROR_STOP=1 -f <file>
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET synchronous_commit = off;
SET maintenance_work_mem = '512MB';

CREATE SEQUENCE invoice_numbers INCREMENT BY 1 MINVALUE 1 START WITH 1020;
CREATE TABLE customers (
    id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    name varchar(100) NOT NULL,
    email varchar(150) NOT NULL,
    country varchar(2) DEFAULT 'US' NOT NULL,
    is_active smallint DEFAULT 1 NOT NULL,
    signed_up timestamp(0),
    created_at timestamp(0) DEFAULT LOCALTIMESTAMP NOT NULL,
    CONSTRAINT customers_check1 CHECK (is_active IN (0, 1))
);

CREATE TABLE orders (
    id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    customer_id bigint NOT NULL,
    invoice bigint DEFAULT (nextval('invoice_numbers')),
    status varchar(10) DEFAULT 'pending' NOT NULL,
    total numeric(10,2) NOT NULL,
    items integer DEFAULT 1 NOT NULL,
    ordered_at timestamp(0) NOT NULL,
    shipped_at timestamp(0),
    note varchar(255),
    CONSTRAINT orders_check1 CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled'))
);

COPY customers (id, name, email, country, is_active, signed_up, created_at) FROM stdin;
1	Ana Martínez	ana@example.com	MX	1	2023-01-15 00:00:00	2023-01-15 10:24:00.000000
2	Zoë Müller	zoe@example.de	DE	1	2023-02-03 00:00:00	2023-02-03 08:11:42.000000
3	José Peña	jose@example.es	ES	0	2023-03-21 00:00:00	2023-03-21 19:05:17.000000
4	李雷	lilei@example.cn	CN	1	2023-05-09 00:00:00	2023-05-09 02:40:00.000000
5	Noah O'Brien	noah@example.ie	IE	1	\N	2023-06-30 14:00:00.000000
6	Amélie Laurent	amelie@example.fr	FR	1	2024-01-02 00:00:00	2024-01-02 09:30:00.000000
7	Ravi Patel	ravi@example.in	IN	0	2024-02-29 00:00:00	2024-02-29 23:59:59.000000
8	Sofia Rossi 🌻	sofia@example.it	IT	1	2024-04-12 00:00:00	2024-04-12 12:12:12.000000
\.

COPY orders (id, customer_id, invoice, status, total, items, ordered_at, shipped_at, note) FROM stdin;
1	1	1000	shipped	129.9	3	2024-03-01 10:00:00	2024-03-02 16:30:00	\N
2	2	1001	paid	54	1	2024-03-02 11:15:00	\N	Gift wrap 🎁
3	1	1002	cancelled	12.5	1	2024-03-03 09:45:00	\N	Customer changed their mind
4	4	1003	shipped	980	12	2024-03-05 02:10:00	2024-03-07 08:00:00	请小心轻放
5	5	1004	pending	45.75	2	2024-03-08 17:20:00	\N	Leave at the door; ring twice
6	6	1005	shipped	310.4	5	2024-03-10 13:00:00	2024-03-11 09:00:00	Fragile: "glass"
7	8	1006	paid	76.2	2	2024-03-11 18:45:00	\N	\N
8	2	1007	paid	19.99	1	2024-03-12 08:00:00	\N	Paid at the counter
9	3	1008	shipped	64	2	2024-03-14 15:30:00	\N	Shipping date never recorded
10	7	1009	paid	1499	1	2024-03-15 21:05:00	\N	C:\\Users\\ravi\\invoice.pdf
\.


-- Keys, indexes and constraints, after the rows so each builds once.
CREATE UNIQUE INDEX customers_customers_pk ON customers (id);
CREATE UNIQUE INDEX customers_customers_email_uk ON customers (email);
CREATE UNIQUE INDEX orders_orders_pk ON orders (id);
CREATE INDEX orders_orders_status_date_ix ON orders (status, ordered_at);
ALTER TABLE customers ADD CONSTRAINT customers_customers_pk PRIMARY KEY USING INDEX customers_customers_pk;
ALTER TABLE customers ADD CONSTRAINT customers_customers_email_uk UNIQUE USING INDEX customers_customers_email_uk;
ALTER TABLE orders ADD CONSTRAINT orders_orders_pk PRIMARY KEY USING INDEX orders_orders_pk;
ALTER TABLE orders ADD CONSTRAINT orders_customer_fk FOREIGN KEY (customer_id) REFERENCES customers (id) NOT VALID;
DO $f$ BEGIN
    ALTER TABLE orders VALIDATE CONSTRAINT orders_customer_fk;
EXCEPTION WHEN foreign_key_violation THEN
    RAISE WARNING 'foreign key % has rows without a parent: it stays NOT VALID, and new rows are checked', 'orders_customer_fk';
END $f$;
SELECT setval(pg_get_serial_sequence('customers', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM customers)::numeric, 0) + 1, 1), 9223372036854775807)::bigint, false);
COMMENT ON TABLE customers IS 'People who bought at least once';
SELECT setval(pg_get_serial_sequence('orders', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM orders)::numeric, 0) + 1, 1), 9223372036854775807)::bigint, false);

Correções

Nada precisou de correção.

Seu arquivo é convertido neste computador e nunca é enviado.

Outros exemplos:

O que muda do Oracle para o PostgreSQL

Cada linha é uma regra que o conversor aplica, com a linha do relatório que ele escreve quando a regra muda algo nos seus dados.

  • BOOLEAN (23ai)

    boolean

    TRUE e FALSE continuam sendo true e false.

  • VARCHAR2(n BYTE|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONG

    varchar(n) e text

    Os tamanhos contam caracteres, quer o Oracle contasse bytes ou caracteres, então todo valor cabe.

  • NUMBER, NUMBER(p,s), FLOAT(b)

    numeric(p,s), ou bigint

    NUMBER mantém cada dígito; um NUMBER sem precisão cujos valores são todos números inteiros de até 18 dígitos vira um inteiro de 64 bits, e uma escala negativa comporta outros tantos dígitos antes do ponto.

  • DATE, TIMESTAMP(p)

    timestamp(p)

    O DATE do Oracle guarda uma hora até o segundo, então é uma data e hora. Uma exportação em uma sessão americana ou alemã escreve as datas sem a hora nem o século (DD-MON-RR); exporte em uma sessão ISO (SYYYY-MM-DD HH24:MI:SS) para mantê-las.

  • TIMESTAMP(7) to TIMESTAMP(9)

    seis dígitos de segundo, o sétimo cortado

    O PostgreSQL guarda microssegundos; o sétimo dígito (100 nanossegundos) é cortado, nunca arredondado, então nenhum valor passa para o segundo ou o dia seguinte.

    Linha do relatório: fraction_cut

  • TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE

    timestamptz, os mesmos instantes

    timestamptz mantém o instante; o PostgreSQL o mostra no fuso horário da sessão em vez do fuso que cada valor tinha.

  • JSON (21c), and CLOB holding JSON

    jsonb

    Os mesmos valores JSON; um NULL do SQL que a exportação escreveu como 'null' continua NULL.

  • BLOB, RAW(n), LONG RAW

    bytea

    Bytes continuam sendo bytes.

  • ROWID, UROWID, XMLTYPE, SDO_GEOMETRY

    text, e xml para XMLTYPE

    Os tipos próprios do Oracle não têm equivalente; seus valores mantêm o texto, incluindo os valores ROWID, embora fora do Oracle não signifiquem nada.

    Linha do relatório: type_replaced

  • collations that ignore case (BINARY_CI)

    comparação exata

    O PostgreSQL compara texto de forma exata, então colunas que ignoravam maiúsculas no Oracle agora diferenciam Ana de ana.

    Linha do relatório: case_insensitive_collation

  • identity columns, and a sequence a BEFORE INSERT trigger assigns

    GENERATED BY DEFAULT AS IDENTITY, continuando depois do maior id

    Os ids copiados carregam como estão, e o contador continua depois do maior deles. Uma coluna que um gatilho preenche a partir de uma sequência (o jeito de antes do 12c) também é de identidade.

  • CREATE SEQUENCE

    CREATE SEQUENCE com as mesmas opções

    A exportação escreve até onde uma sequência chegou como o seu START WITH, então ela continua dali.

  • virtual columns (GENERATED ALWAYS AS ... VIRTUAL)

    colunas geradas, STORED

    O PostgreSQL 13 a 17 só armazena colunas geradas; a fórmula é a mesma, com || escrito para que NULL conte como vazio, como no Oracle.

    Linha do relatório: virtual_as_stored

  • virtual columns with functions IntoSQL doesn't write, and the || operator

    uma coluna simples

    Uma fórmula que não pode ser escrita para o PostgreSQL deixa uma coluna simples e uma linha no relatório; os valores que a exportação escreveu para colunas virtuais ficam de fora, e o PostgreSQL não tem nenhum para calcular.

    Linha do relatório: generated_not_translated

  • defaults with functions IntoSQL doesn't write (SYS_GUID(), ||)

    sem valor padrão

    Um valor padrão que não pode ser escrito para o PostgreSQL fica de fora e é informado no relatório.

    Linha do relatório: default_not_translated

  • CHECK constraints

    traduzidos

    Os mesmos CHECKs, testados à medida que cada linha carrega.

  • CHECK constraints with functions IntoSQL doesn't write

    não criado

    Um CHECK que não pode ser escrito para o PostgreSQL fica de fora e é informado no relatório.

    Linha do relatório: check_skipped

  • CHECK constraints that are DISABLE or ENABLE NOVALIDATE

    não criado

    O Oracle não aplica esses CHECKs às linhas que já existiam, então as linhas podem violá-los.

    Linha do relatório: check_not_enforced

  • function-based, bitmap and domain indexes

    não criado

    O IntoSQL escreve índices b-tree sobre colunas; crie os outros de novo depois da carga.

    Linha do relatório: index_skipped

  • foreign keys

    chaves estrangeiras, depois das linhas

    As linhas carregam em qualquer ordem, e as chaves as verificam depois.

  • foreign keys to tables the export doesn't create, and DISABLE or NOVALIDATE ones

    não criada

    Uma chave não pode apontar para uma tabela que não existe, e uma que o Oracle não verifica pode ter linhas sem pai.

    Linha do relatório: foreign_key_skipped

  • partitioned tables

    uma tabela com as linhas de todas as partições

    As linhas são as mesmas; particione a tabela de novo no PostgreSQL se precisar.

    Linha do relatório: partitions_dropped

  • NOT NULL columns with values that become NULL

    NOT NULL removido

    Uma coluna cujos valores tiveram de virar NULL não pode manter NOT NULL, senão a carga pararia.

    Linha do relatório: not_null_relaxed

  • views, synonyms, types, packages, procedures, functions and other triggers

    listados no relatório

    O código deles é escrito em PL/SQL, então eles são listados para você recriá-los.

    Linha do relatório: not_converted_objects

  • exports without CREATE TABLE (data only)

    tipos lidos dos valores

    Uma exportação só de dados tem apenas linhas, então os tipos vêm dos valores.

    Linha do relatório: no_schema

  • expressions in INSERT values other than the ones exports write

    NULL

    Um conversor que não executa um banco de dados não consegue avaliá-las; to_date, to_timestamp, TO_CLOB, HEXTORAW e as outras que as exportações escrevem são lidas.

    Linha do relatório: expression_value

  • types IntoSQL doesn't know, and object types

    text

    O texto aceita qualquer valor; mude o tipo depois da carga.

    Linha do relatório: unknown_type

  • dates before year 1 and time zones given as region names

    NULL

    Um valor que não é uma data vira NULL e o relatório o conta.

    Linha do relatório: date_out_of_range

  • NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLE

    NaN e Infinity mantidos

    Os tipos de ponto flutuante do PostgreSQL comportam NaN e infinito.

  • NUL characters in text

    removido

    O texto do PostgreSQL não aceita o caractere NUL. Ele é removido e o relatório conta os valores.

    Linha do relatório: nul_removed

  • text that isn't valid in its encoding

    os bytes inválidos como o caractere de substituição

    O texto do PostgreSQL precisa ser UTF-8 válido.

    Linha do relatório: invalid_utf8_replaced

  • text decoded twice (ñ)

    copiado como está

    O script contém exatamente esses caracteres, então eles são copiados; o relatório os aponta.

    Linha do relatório: mojibake_suspected

No OracleNo PostgreSQLLinha do relatório
BOOLEAN (23ai)booleanTRUE e FALSE continuam sendo true e false.
VARCHAR2(n BYTE|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONGvarchar(n) e textOs tamanhos contam caracteres, quer o Oracle contasse bytes ou caracteres, então todo valor cabe.
NUMBER, NUMBER(p,s), FLOAT(b)numeric(p,s), ou bigintNUMBER mantém cada dígito; um NUMBER sem precisão cujos valores são todos números inteiros de até 18 dígitos vira um inteiro de 64 bits, e uma escala negativa comporta outros tantos dígitos antes do ponto.
DATE, TIMESTAMP(p)timestamp(p)O DATE do Oracle guarda uma hora até o segundo, então é uma data e hora. Uma exportação em uma sessão americana ou alemã escreve as datas sem a hora nem o século (DD-MON-RR); exporte em uma sessão ISO (SYYYY-MM-DD HH24:MI:SS) para mantê-las.
TIMESTAMP(7) to TIMESTAMP(9)seis dígitos de segundo, o sétimo cortadoO PostgreSQL guarda microssegundos; o sétimo dígito (100 nanossegundos) é cortado, nunca arredondado, então nenhum valor passa para o segundo ou o dia seguinte.fraction_cut
TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONEtimestamptz, os mesmos instantestimestamptz mantém o instante; o PostgreSQL o mostra no fuso horário da sessão em vez do fuso que cada valor tinha.
JSON (21c), and CLOB holding JSONjsonbOs mesmos valores JSON; um NULL do SQL que a exportação escreveu como 'null' continua NULL.
BLOB, RAW(n), LONG RAWbyteaBytes continuam sendo bytes.
ROWID, UROWID, XMLTYPE, SDO_GEOMETRYtext, e xml para XMLTYPEOs tipos próprios do Oracle não têm equivalente; seus valores mantêm o texto, incluindo os valores ROWID, embora fora do Oracle não signifiquem nada.type_replaced
collations that ignore case (BINARY_CI)comparação exataO PostgreSQL compara texto de forma exata, então colunas que ignoravam maiúsculas no Oracle agora diferenciam Ana de ana.case_insensitive_collation
identity columns, and a sequence a BEFORE INSERT trigger assignsGENERATED BY DEFAULT AS IDENTITY, continuando depois do maior idOs ids copiados carregam como estão, e o contador continua depois do maior deles. Uma coluna que um gatilho preenche a partir de uma sequência (o jeito de antes do 12c) também é de identidade.
CREATE SEQUENCECREATE SEQUENCE com as mesmas opçõesA exportação escreve até onde uma sequência chegou como o seu START WITH, então ela continua dali.
virtual columns (GENERATED ALWAYS AS ... VIRTUAL)colunas geradas, STOREDO PostgreSQL 13 a 17 só armazena colunas geradas; a fórmula é a mesma, com || escrito para que NULL conte como vazio, como no Oracle.virtual_as_stored
virtual columns with functions IntoSQL doesn't write, and the || operatoruma coluna simplesUma fórmula que não pode ser escrita para o PostgreSQL deixa uma coluna simples e uma linha no relatório; os valores que a exportação escreveu para colunas virtuais ficam de fora, e o PostgreSQL não tem nenhum para calcular.generated_not_translated
defaults with functions IntoSQL doesn't write (SYS_GUID(), ||)sem valor padrãoUm valor padrão que não pode ser escrito para o PostgreSQL fica de fora e é informado no relatório.default_not_translated
CHECK constraintstraduzidosOs mesmos CHECKs, testados à medida que cada linha carrega.
CHECK constraints with functions IntoSQL doesn't writenão criadoUm CHECK que não pode ser escrito para o PostgreSQL fica de fora e é informado no relatório.check_skipped
CHECK constraints that are DISABLE or ENABLE NOVALIDATEnão criadoO Oracle não aplica esses CHECKs às linhas que já existiam, então as linhas podem violá-los.check_not_enforced
function-based, bitmap and domain indexesnão criadoO IntoSQL escreve índices b-tree sobre colunas; crie os outros de novo depois da carga.index_skipped
foreign keyschaves estrangeiras, depois das linhasAs linhas carregam em qualquer ordem, e as chaves as verificam depois.
foreign keys to tables the export doesn't create, and DISABLE or NOVALIDATE onesnão criadaUma chave não pode apontar para uma tabela que não existe, e uma que o Oracle não verifica pode ter linhas sem pai.foreign_key_skipped
partitioned tablesuma tabela com as linhas de todas as partiçõesAs linhas são as mesmas; particione a tabela de novo no PostgreSQL se precisar.partitions_dropped
NOT NULL columns with values that become NULLNOT NULL removidoUma coluna cujos valores tiveram de virar NULL não pode manter NOT NULL, senão a carga pararia.not_null_relaxed
views, synonyms, types, packages, procedures, functions and other triggerslistados no relatórioO código deles é escrito em PL/SQL, então eles são listados para você recriá-los.not_converted_objects
exports without CREATE TABLE (data only)tipos lidos dos valoresUma exportação só de dados tem apenas linhas, então os tipos vêm dos valores.no_schema
expressions in INSERT values other than the ones exports writeNULLUm conversor que não executa um banco de dados não consegue avaliá-las; to_date, to_timestamp, TO_CLOB, HEXTORAW e as outras que as exportações escrevem são lidas.expression_value
types IntoSQL doesn't know, and object typestextO texto aceita qualquer valor; mude o tipo depois da carga.unknown_type
dates before year 1 and time zones given as region namesNULLUm valor que não é uma data vira NULL e o relatório o conta.date_out_of_range
NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLENaN e Infinity mantidosOs tipos de ponto flutuante do PostgreSQL comportam NaN e infinito.
NUL characters in textremovidoO texto do PostgreSQL não aceita o caractere NUL. Ele é removido e o relatório conta os valores.nul_removed
text that isn't valid in its encodingos bytes inválidos como o caractere de substituiçãoO texto do PostgreSQL precisa ser UTF-8 válido.invalid_utf8_replaced
text decoded twice (ñ)copiado como estáO script contém exatamente esses caracteres, então eles são copiados; o relatório os aponta.mojibake_suspected

Carregue o script no PostgreSQL

O script cria as tabelas, copia as linhas e depois adiciona chaves, índices e chaves estrangeiras, então carrega rápido e para no primeiro erro.

psql -v ON_ERROR_STOP=1 -d mydb -f oracle.postgresql.sql

As chaves estrangeiras são adicionadas como NOT VALID e depois validadas. Se uma linha aponta para uma linha que não existe, o script informa qual restrição, em vez de falhar no meio do caminho.

Para um dump grande, crie o banco de dados antes e execute o script com o psql na mesma máquina do servidor.

O IntoSQL Pro carrega o arquivo direto no PostgreSQL pelo app para desktop ou pela linha de comando, sem escrever um script.

Gere o dump do Oracle para o melhor resultado

O conversor lê o que o dump contém. Estas opções mantêm mais dos seus dados nele:

  • No SQL Developer, escolha Tools, Database Export, com DDL e o formato de dados Insert. O SQLcl escreve o mesmo com SET SQLFORMAT INSERT.
  • Rode ALTER SESSION SET NLS_DATE_FORMAT = 'SYYYY-MM-DD HH24:MI:SS' antes de exportar: o formato padrão escreve as datas sem a hora nem o século.
  • Um arquivo .dmp do exp ou do expdp é binário: importe-o em um banco de dados Oracle, como o Oracle Database Free no Docker, e exporte-o com o SQL Developer.

O que não é convertido

Visões, pacotes, procedimentos, funções, gatilhos, tipos e sinônimos são escritos em PL/SQL. Eles aparecem no relatório pelo nome, nunca são descartados em silêncio, para que você possa reescrevê-los para o PostgreSQL.

Perguntas sobre Oracle para PostgreSQL

Não encontrou a resposta? Escreva para nós pela página de contato e uma pessoa responde. Página de contato

Meu dump é enviado?

Não. O conversor roda no seu navegador e lê o dump do seu disco em partes, então ele nunca sai do seu computador. O app para desktop e a linha de comando também convertem no seu computador.

Qual o tamanho máximo do dump?

O conversor nunca guarda o dump inteiro na memória: ele lê o arquivo duas vezes, por intervalos, e escreve o script à medida que avança. Dumps de vários gigabytes são convertidos no navegador, no app para desktop e com a linha de comando.

Posso converter um arquivo .dmp do exp ou do expdp?

Não diretamente: o Data Pump e o Export original escrevem um formato binário que só o Oracle lê. Importe-o em qualquer banco de dados Oracle, o Oracle Database Free roda no Docker, e exporte-o com o Database Export do SQL Developer ou com o SQLcl. O conversor avisa quando recebe um arquivo .dmp.

De quais versões do Oracle a exportação pode vir?

Exportações do SQL Developer e do SQLcl, com as definições de tabela do DBMS_METADATA, a partir do Oracle 11g. Cada exportação de teste vem do Oracle 21c e 23ai, em sessões americanas, alemãs e ISO, e é comparada com a origem célula por célula.

O que acontece com NUMBER, DATE e os outros tipos do Oracle?

NUMBER vira numeric, ou bigint quando todo valor é um número inteiro; DATE vira timestamp, mantendo a hora; CLOB text, BLOB e RAW bytea, BINARY_DOUBLE double precision com NaN e Infinity, e os intervalos interval.

As colunas de identidade e as sequências são mantidas?

Sim. As colunas de identidade continuam colunas de identidade e continuam depois do maior id, e o mesmo vale para uma coluna que um gatilho preenche a partir de uma sequência. As sequências continuam de onde a exportação diz que chegaram.

E os pacotes, procedimentos e gatilhos em PL/SQL?

Eles aparecem no relatório pelo nome e não são convertidos, porque cada banco de dados os escreve na sua própria linguagem.

Em quais versões do PostgreSQL o script carrega?

PostgreSQL 13 a 18. O mesmo script carrega em cada uma delas e para no primeiro erro se algo der errado.