Pular para o conteúdo
Início do IntoSQL

Converta SQLite para Oracle

Solte um arquivo de banco de dados SQLite (.db, .sqlite, .sqlite3) ou o SQL que o .dump do sqlite3 escreve, e baixe um script do Oracle com as mesmas tabelas, chaves, índices e dados. Cada coluna recebe o tipo em que seus valores cabem, e cada valor que o Oracle não aceita como está aparece no relatório.

Seu arquivo
sqlshop_2024_sqlite.sqlArquivo de exemplo, 3,4 kB
Seu banco de dados

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

Mostrar

Tabelas em shop_2024_sqlite.sqlDump do SQLite · gerado por sqlite3 · utf-8

  • customersescrita como CUSTOMERS8 linhas
    7 colunas
    IDNUMBER(19) not null
    NAMEVARCHAR2(4000 CHAR) not null
    EMAILVARCHAR2(750 CHAR) not null
    COUNTRYVARCHAR2(4000 CHAR) not null
    IS_ACTIVENUMBER(1) not null
    SIGNED_UPDATE
    CREATED_ATTIMESTAMP(0) not null
  • ordersescrita como ORDERS10 linhas
    9 colunas
    IDNUMBER(19) not null
    CUSTOMER_IDNUMBER(19) not null
    STATUSVARCHAR2(750 CHAR) not null
    TOTALNUMBER(10,2) not null
    ITEMSNUMBER(10) not null
    ORDERED_ATTIMESTAMP(0) not null
    SHIPPED_ATTIMESTAMP(0)
    NOTEVARCHAR2(4000 CHAR)
    RECEIPTBLOB

Não convertidos

  • Visão order_totals
  • Gatilho orders_shipped

Cada banco de dados escreve estes objetos na sua própria linguagem. Reescreva-os para o Oracle.

-- Written by IntoSQL from a SQLite 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(19) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 9),
    "NAME" VARCHAR2(4000 CHAR) NOT NULL,
    "EMAIL" VARCHAR2(750 CHAR) NOT NULL,
    "COUNTRY" VARCHAR2(4000 CHAR) DEFAULT 'US' NOT NULL,
    "IS_ACTIVE" NUMBER(1) DEFAULT 1 NOT NULL,
    "SIGNED_UP" DATE,
    "CREATED_AT" TIMESTAMP(0) DEFAULT LOCALTIMESTAMP NOT NULL,
    CONSTRAINT "CK_CUSTOMERS_IS_ACTIVE" CHECK ("IS_ACTIVE" IN (0, 1)),
    CONSTRAINT "CHECK1" CHECK (LENGTH("COUNTRY") = 2)
);

CREATE TABLE "ORDERS" (
    "ID" NUMBER(19) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 11),
    "CUSTOMER_ID" NUMBER(19) NOT NULL,
    "STATUS" VARCHAR2(750 CHAR) DEFAULT 'pending' NOT NULL,
    "TOTAL" NUMBER(10,2) NOT NULL,
    "ITEMS" NUMBER(10) DEFAULT 1 NOT NULL,
    "ORDERED_AT" TIMESTAMP(0) NOT NULL,
    "SHIPPED_AT" TIMESTAMP(0),
    "NOTE" VARCHAR2(4000 CHAR),
    "RECEIPT" BLOB,
    CONSTRAINT "CHECK1_2" CHECK ("STATUS" IN ('pending', 'paid', 'shipped', 'cancelled'))
);

BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
1,
'Ana Martínez',
'ana@example.com',
'MX',
1,
DATE '2023-01-15',
TIMESTAMP '2023-01-15 10:24:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"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'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
3,
'José Peña',
'jose@example.es',
'ES',
0,
DATE '2023-03-21',
TIMESTAMP '2023-03-21 19:05:17'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
4,
'李雷',
'lilei@example.cn',
'CN',
1,
DATE '2023-05-09',
TIMESTAMP '2023-05-09 02:40:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
5,
'Noah O''Brien',
'noah@example.ie',
'IE',
1,
NULL,
TIMESTAMP '2023-06-30 14:00:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
6,
'Amélie Laurent',
'amelie@example.fr',
'FR',
1,
DATE '2024-01-02',
TIMESTAMP '2024-01-02 09:30:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
7,
'Ravi Patel',
'ravi@example.in',
'IN',
0,
DATE '2024-02-29',
TIMESTAMP '2024-02-29 23:59:59'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
8,
'Sofia Rossi 🌻',
'sofia@example.it',
'IT',
1,
DATE '2024-04-12',
TIMESTAMP '2024-04-12 12:12:12'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
1,
1,
'shipped',
129.9,
3,
TIMESTAMP '2024-03-01 10:00:00',
TIMESTAMP '2024-03-02 16:30:00',
NULL,
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
2,
2,
'paid',
54,
1,
TIMESTAMP '2024-03-02 11:15:00',
NULL,
'Gift wrap 🎁',
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
3,
1,
'cancelled',
12.5,
1,
TIMESTAMP '2024-03-03 09:45:00',
NULL,
'Customer changed their mind',
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
4,
4,
'shipped',
980,
12,
TIMESTAMP '2024-03-05 02:10:00',
TIMESTAMP '2024-03-07 08:00:00',
'请小心轻放',
HEXTORAW('25504446')
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
5,
5,
'pending',
45.75,
2,
TIMESTAMP '2024-03-08 17:20:00',
NULL,
'Leave at the door;'
|| CHR(10)
|| 'ring twice',
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
6,
6,
'shipped',
310.4,
5,
TIMESTAMP '2024-03-10 13:00:00',
TIMESTAMP '2024-03-11 09:00:00',
'Fragile: "glass"',
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
7,
8,
'paid',
76.2,
2,
TIMESTAMP '2024-03-11 18:45:00',
NULL,
NULL,
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
8,
2,
'paid',
19.99,
1,
TIMESTAMP '2024-03-12 08:00:00',
NULL,
'Paid at the counter',
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
9,
3,
'shipped',
64,
2,
TIMESTAMP '2024-03-14 15:30:00',
NULL,
'Shipping date never recorded',
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"RECEIPT"
) VALUES (
10,
7,
'paid',
1499,
1,
TIMESTAMP '2024-03-15 21:05:00',
NULL,
'C:\Users\ravi\invoice.pdf',
NULL
);
COMMIT;
END;
/

-- Keys, indexes, foreign keys, counters and triggers, after the rows.
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "PK_CUSTOMERS" PRIMARY KEY ("ID");
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "UQ_CUSTOMERS_EMAIL" UNIQUE ("EMAIL");
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 "FK_ORDERS" FOREIGN KEY ("CUSTOMER_ID") REFERENCES "CUSTOMERS" ("ID") ON DELETE CASCADE ENABLE NOVALIDATE;
BEGIN
    EXECUTE IMMEDIATE 'ALTER TABLE "ORDERS" ENABLE VALIDATE CONSTRAINT "FK_ORDERS"';
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Foreign key ' || '"FK_ORDERS"' || ' 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 < 9 THEN
        next_id := 9;
    END IF;
    EXECUTE IMMEDIATE 'ALTER TABLE "CUSTOMERS" MODIFY ("ID" GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH ' || next_id || '))';
END;
/
DECLARE
    next_id NUMBER;
BEGIN
    SELECT NVL(MAX("ID"), 0) + 1 INTO next_id FROM "ORDERS";
    IF next_id < 11 THEN
        next_id := 11;
    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;

Correções

Nada precisou de correção.

Para revisar

  • 1 coluna de texto compara sem diferenciar maiúsculas na origem; o Oracle compara de forma exata, então chaves únicas e buscas podem se comportar de outro jeito. Use uma collation ou um tipo de coluna sem diferenciação de maiúsculas nas colunas que precisarem.
  • 2 visões, gatilhos, rotinas ou eventos não foram convertidos; o relatório lista cada um. Recrie-os manualmente no Oracle.

Seu arquivo é convertido neste computador e nunca é enviado.

Outros exemplos:

O que muda do SQLite para o Oracle

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.

  • declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none)

    o tipo em que cabem todos os valores da coluna

    O SQLite guarda qualquer valor em qualquer coluna, então o tipo declarado é uma dica: cada coluna recebe o tipo em que cabem todos os seus valores, e uma coluna com valores misturados mantém o texto deles.

  • BOOLEAN, BOOL

    NUMBER(1) com um CHECK de 0 e 1

    Quando todo valor é 0 ou 1; uma coluna que também tem outros valores os mantém como números ou texto.

  • TEXT, VARCHAR(n), CHAR(n), CLOB

    VARCHAR2(n CHAR) quando todo valor cabe, senão CLOB

    O SQLite nunca impõe um tamanho; um tamanho declarado só vale quando todo valor cabe nele.

  • TEXT and VARCHAR(n) longer than 4000 bytes

    VARCHAR2(4000 CHAR) quando todo valor cabe em 4000 bytes (750 caracteres em uma chave), senão CLOB

    Um VARCHAR2 comporta 4000 bytes por padrão e o Oracle não indexa um CLOB, então o texto fica VARCHAR2 quando seus valores cabem e vira CLOB quando não cabem.

    Linha do relatório: text_as_lob

  • DECIMAL(p,s), NUMERIC

    o tipo exato quando todo valor cabe nele, senão um double

    O SQLite os guarda como inteiros ou doubles; uma precisão declarada só vale quando os valores cabem nela.

  • BLOB, and columns holding bytes

    BLOB

    Bytes continuam bytes; texto e números na mesma coluna são mantidos como seus bytes.

  • DATE, DATETIME, TIMESTAMP holding ISO 8601 text

    DATE ou TIMESTAMP(p), conforme o que os valores contêm

    Quando todo valor é uma data ou uma data e hora; números epoch e outros textos mantêm seus valores como estão.

  • JSON holding JSON text

    CLOB

    Quando todo valor é um objeto ou array JSON.

  • Infinity in REAL columns

    mantido como BINARY_DOUBLE_INFINITY

    Os doubles do Oracle comportam o infinito.

  • INTEGER PRIMARY KEY, AUTOINCREMENT

    GENERATED BY DEFAULT ON NULL AS IDENTITY, continuando depois do maior id ou do valor de sqlite_sequence

    Só uma coluna declarada exatamente como INTEGER PRIMARY KEY é o rowid; cada linha mantém seu id, e o contador começa depois do maior id já atribuído.

  • COLLATE NOCASE

    comparação exata

    O Oracle compara texto de forma exata, a menos que se indique outra coisa; colunas NOCASE deixam de ignorar maiúsculas.

    Linha do relatório: case_insensitive_collation

  • generated columns

    colunas virtuais

    O Oracle só calcula colunas geradas na leitura; colunas STORED viram virtuais com os mesmos valores.

    Linha do relatório: stored_as_virtual

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

    uma coluna simples

    Uma fórmula que não pode ser escrita deixa uma coluna simples e uma linha no relatório; o dump não tem valores para colunas geradas.

    Linha do relatório: generated_not_translated

  • defaults with functions IntoSQL doesn't write (strftime, randomblob)

    sem valor padrão

    Um valor padrão que não pode ser escrito fica de fora e é informado; CURRENT_TIMESTAMP e datetime('now') são escritos.

    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 fica de fora e é informado.

    Linha do relatório: check_skipped

  • partial and expression indexes

    não criado

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

    Linha do relatório: index_skipped

  • foreign keys (unenforced unless PRAGMA foreign_keys=ON)

    depois dos dados ENABLE NOVALIDATE, e então validada

    O SQLite só verifica chaves estrangeiras quando instruído, então linhas sem pai são comuns: elas carregam, e a chave fica sem verificação com um aviso, em vez de parar a carga.

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

    descartado

    As chaves estrangeiras do Oracle só agem na exclusão, com CASCADE ou SET NULL.

    Linha do relatório: foreign_key_action_unsupported

  • empty strings and empty blobs

    NULL

    O Oracle guarda uma string vazia como NULL, então um valor que era ' é lido de volta como NULL. O relatório os conta por coluna.

    Linha do relatório: empty_string_null

  • foreign keys to tables the dump doesn't create

    não criada

    Uma chave não pode apontar para uma tabela que não existe.

    Linha do relatório: foreign_key_skipped

  • primary keys holding NULL, and NOT NULL columns with values that become NULL

    NOT NULL removido

    O SQLite deixa uma chave primária que não seja o rowid conter NULL; a coluna não pode ser NOT NULL no destino, senão a carga pararia.

    Linha do relatório: not_null_relaxed

  • views, triggers and virtual tables (FTS, R*Tree)

    listados no relatório

    O código deles é escrito na linguagem própria do SQLite, e tabelas virtuais precisam dos módulos do SQLite; eles são listados para você recriar. As tabelas internas deles não são copiadas.

    Linha do relatório: not_converted_objects

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

    tipos lidos dos valores

    Um dump só de dados tem apenas linhas, então os tipos vêm dos valores e as colunas são numeradas.

    Linha do relatório: no_schema

  • expressions in INSERT values other than the text functions dumps write

    NULL

    unistr(), replace(), char() e || são avaliados como o shell os escreve; as outras expressões não podem ser avaliadas sem um banco de dados.

    Linha do relatório: expression_value

  • NUL characters in text

    mantido

    O shell sqlite3 e o Python cortam o texto em um caractere NUL ao gerar o dump, então só o que vem antes dele está no dump.

  • text that isn't valid UTF-8

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

    Os dumps escrevem esse texto como bytes brutos; o script é UTF-8.

    Linha do relatório: invalid_utf8_replaced

  • text decoded twice (ñ)

    copiado como está

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

    Linha do relatório: mojibake_suspected

No SQLiteNo OracleLinha do relatório
declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none)o tipo em que cabem todos os valores da colunaO SQLite guarda qualquer valor em qualquer coluna, então o tipo declarado é uma dica: cada coluna recebe o tipo em que cabem todos os seus valores, e uma coluna com valores misturados mantém o texto deles.
BOOLEAN, BOOLNUMBER(1) com um CHECK de 0 e 1Quando todo valor é 0 ou 1; uma coluna que também tem outros valores os mantém como números ou texto.
TEXT, VARCHAR(n), CHAR(n), CLOBVARCHAR2(n CHAR) quando todo valor cabe, senão CLOBO SQLite nunca impõe um tamanho; um tamanho declarado só vale quando todo valor cabe nele.
TEXT and VARCHAR(n) longer than 4000 bytesVARCHAR2(4000 CHAR) quando todo valor cabe em 4000 bytes (750 caracteres em uma chave), senão CLOBUm VARCHAR2 comporta 4000 bytes por padrão e o Oracle não indexa um CLOB, então o texto fica VARCHAR2 quando seus valores cabem e vira CLOB quando não cabem.text_as_lob
DECIMAL(p,s), NUMERICo tipo exato quando todo valor cabe nele, senão um doubleO SQLite os guarda como inteiros ou doubles; uma precisão declarada só vale quando os valores cabem nela.
BLOB, and columns holding bytesBLOBBytes continuam bytes; texto e números na mesma coluna são mantidos como seus bytes.
DATE, DATETIME, TIMESTAMP holding ISO 8601 textDATE ou TIMESTAMP(p), conforme o que os valores contêmQuando todo valor é uma data ou uma data e hora; números epoch e outros textos mantêm seus valores como estão.
JSON holding JSON textCLOBQuando todo valor é um objeto ou array JSON.
Infinity in REAL columnsmantido como BINARY_DOUBLE_INFINITYOs doubles do Oracle comportam o infinito.
INTEGER PRIMARY KEY, AUTOINCREMENTGENERATED BY DEFAULT ON NULL AS IDENTITY, continuando depois do maior id ou do valor de sqlite_sequenceSó uma coluna declarada exatamente como INTEGER PRIMARY KEY é o rowid; cada linha mantém seu id, e o contador começa depois do maior id já atribuído.
COLLATE NOCASEcomparação exataO Oracle compara texto de forma exata, a menos que se indique outra coisa; colunas NOCASE deixam de ignorar maiúsculas.case_insensitive_collation
generated columnscolunas virtuaisO Oracle só calcula colunas geradas na leitura; colunas STORED viram virtuais com os mesmos valores.stored_as_virtual
generated columns with functions IntoSQL doesn't write, and the || operatoruma coluna simplesUma fórmula que não pode ser escrita deixa uma coluna simples e uma linha no relatório; o dump não tem valores para colunas geradas.generated_not_translated
defaults with functions IntoSQL doesn't write (strftime, randomblob)sem valor padrãoUm valor padrão que não pode ser escrito fica de fora e é informado; CURRENT_TIMESTAMP e datetime('now') são escritos.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 fica de fora e é informado.check_skipped
partial and expression indexesnão criadoO IntoSQL escreve índices sobre colunas inteiras; crie os outros de novo depois da carga.index_skipped
foreign keys (unenforced unless PRAGMA foreign_keys=ON)depois dos dados ENABLE NOVALIDATE, e então validadaO SQLite só verifica chaves estrangeiras quando instruído, então linhas sem pai são comuns: elas carregam, e a chave fica sem verificação com um aviso, em vez de parar a carga.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULTdescartadoAs chaves estrangeiras do Oracle só agem na exclusão, com CASCADE ou SET NULL.foreign_key_action_unsupported
empty strings and empty blobsNULLO Oracle guarda uma string vazia como NULL, então um valor que era ' é lido de volta como NULL. O relatório os conta por coluna.empty_string_null
foreign keys to tables the dump doesn't createnão criadaUma chave não pode apontar para uma tabela que não existe.foreign_key_skipped
primary keys holding NULL, and NOT NULL columns with values that become NULLNOT NULL removidoO SQLite deixa uma chave primária que não seja o rowid conter NULL; a coluna não pode ser NOT NULL no destino, senão a carga pararia.not_null_relaxed
views, triggers and virtual tables (FTS, R*Tree)listados no relatórioO código deles é escrito na linguagem própria do SQLite, e tabelas virtuais precisam dos módulos do SQLite; eles são listados para você recriar. As tabelas internas deles não são copiadas.not_converted_objects
dumps without CREATE TABLE (--data-only)tipos lidos dos valoresUm dump só de dados tem apenas linhas, então os tipos vêm dos valores e as colunas são numeradas.no_schema
expressions in INSERT values other than the text functions dumps writeNULLunistr(), replace(), char() e || são avaliados como o shell os escreve; as outras expressões não podem ser avaliadas sem um banco de dados.expression_value
NUL characters in textmantidoO shell sqlite3 e o Python cortam o texto em um caractere NUL ao gerar o dump, então só o que vem antes dele está no dump.
text that isn't valid UTF-8os bytes inválidos como o caractere de substituiçãoOs dumps escrevem esse texto como bytes brutos; o script é UTF-8.invalid_utf8_replaced
text decoded twice (ñ)copiado como estáO dump contém exatamente esses caracteres, então eles são copiados; o relatório os aponta.mojibake_suspected

Carregue o script no Oracle

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.

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

As chaves estrangeiras são adicionadas ENABLE NOVALIDATE, então as linhas novas são verificadas na hora, e depois validadas. Se uma linha antiga aponta para uma linha que não existe, o script informa qual restrição e a deixa sem validação, em vez de falhar no meio do caminho.

Para um dump grande, execute o SQL*Plus na mesma máquina do banco de dados. O script faz commit a cada 100 linhas. O usuário que o executa precisa de CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER e CREATE PROCEDURE, e de cota no seu tablespace.

Gere o dump do SQLite para o melhor resultado

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

  • O próprio arquivo do banco é convertido como está, lido página por página no navegador. Feche antes o app que escreve nele, para que nenhuma mudança fique para trás no arquivo -wal.
  • sqlite3 app.db .dump > app.sql escreve o mesmo banco de dados como SQL, que também é convertido, em .sql ou .sql.gz.
  • O DB Browser for SQLite escreve esse SQL com File, Export, Database to SQL file, e o iterdump() do Python também.

O que não é convertido

Visões e gatilhos são escritos na linguagem própria do SQLite. Eles aparecem no relatório pelo nome, nunca são descartados em silêncio, para que você possa reescrevê-los para o Oracle. Tabelas virtuais, como FTS5 e R*Tree, também aparecem, e suas tabelas internas ficam de fora.

Perguntas sobre SQLite para Oracle

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 o próprio arquivo .db?

Sim. Solte o arquivo .db, .sqlite ou .sqlite3: ele é lido no navegador e nunca é enviado. Textos com caracteres NUL e todos os dígitos de um double chegam como foram armazenados, algo que um .dump pode cortar.

De quais versões do SQLite o dump pode vir?

Arquivos de banco de dados do SQLite 3.0 em diante, em UTF-8 ou UTF-16, e dumps do .dump do shell sqlite3 ou do iterdump() do Python. Cada arquivo e dump de teste vem do sqlite3 3.31 a 3.54, incluindo tabelas STRICT e WITHOUT ROWID, e é comparado com a origem célula por célula.

Como os tipos de coluna são decididos quando o SQLite não os impõe?

O tipo declarado é uma dica e os valores decidem: uma coluna vira NUMBER, BINARY_DOUBLE, DATE, TIMESTAMP, BLOB, VARCHAR2 ou CLOB quando todo valor cabe nele. Strings vazias viram NULL, como o Oracle as guarda, e o relatório as conta.

INTEGER PRIMARY KEY e AUTOINCREMENT são mantidos?

Sim. Uma INTEGER PRIMARY KEY vira uma coluna identity, cada linha mantém seu id, e o próximo id continua depois do maior, ou depois do valor de sqlite_sequence com AUTOINCREMENT.

E as visões e os gatilhos?

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 Oracle o script carrega?

Oracle 19c e posteriores. Cada dump de teste carrega no 21c e no 23ai e para no primeiro erro se algo der errado.