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.
18 linhas convertidas, nenhuma correção, nenhuma rejeitada
Tabelas em shop_2024_sqlite.sqlDump do SQLite · gerado por sqlite3 · utf-8
customersescrita como CUSTOMERS8 linhas
7 colunas ID NUMBER(19) not null NAME VARCHAR2(4000 CHAR) not null EMAIL VARCHAR2(750 CHAR) not null COUNTRY VARCHAR2(4000 CHAR) not null IS_ACTIVE NUMBER(1) not null SIGNED_UP DATE CREATED_AT TIMESTAMP(0) not null ordersescrita como ORDERS10 linhas
9 colunas ID NUMBER(19) not null CUSTOMER_ID NUMBER(19) not null STATUS VARCHAR2(750 CHAR) not null TOTAL NUMBER(10,2) not null ITEMS NUMBER(10) not null ORDERED_AT TIMESTAMP(0) not null SHIPPED_AT TIMESTAMP(0) NOTE VARCHAR2(4000 CHAR) RECEIPT BLOB
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 SQLite | No Oracle | Linha 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, BOOL | NUMBER(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), CLOB | VARCHAR2(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 bytes | VARCHAR2(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), NUMERIC | o 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 bytes | BLOBBytes 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ê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 text | CLOBQuando todo valor é um objeto ou array JSON. | |
| Infinity in REAL columns | mantido como BINARY_DOUBLE_INFINITYOs 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_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 NOCASE | comparaçã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 columns | colunas 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 || operator | uma 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 constraints | traduzidosOs mesmos CHECKs, testados à medida que cada linha carrega. | |
| CHECK constraints with functions IntoSQL doesn't write | não criadoUm CHECK que não pode ser escrito fica de fora e é informado. | check_skipped |
| partial and expression indexes | nã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 DEFAULT | descartadoAs chaves estrangeiras do Oracle só agem na exclusão, com CASCADE ou SET NULL. | foreign_key_action_unsupported |
| empty strings and empty blobs | NULLO 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 create | nã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 NULL | NOT 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 write | NULLunistr(), 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 text | mantidoO 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çã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.sqlAs 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.