Converti SQLite in Oracle
Trascina un file di database SQLite (.db, .sqlite, .sqlite3) o il SQL che scrive il .dump di sqlite3, e scarica uno script per Oracle con le stesse tabelle, chiavi, indici e dati. Ogni colonna riceve il tipo in cui stanno i suoi valori, e ogni valore che Oracle non può contenere così com'è è elencato nel report.
18 righe convertite, nessuna correzione, nessuna rifiutata
Tabelle in shop_2024_sqlite.sqlDump SQLite · scritto da sqlite3 · utf-8
customersscritta come CUSTOMERS8 righe
7 colonne 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 ordersscritta come ORDERS10 righe
9 colonne 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
Non convertiti
- Vista order_totals
- Trigger orders_shipped
Ogni database li scrive nel proprio linguaggio. Riscrivili per 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;
Correzioni
Non c'era niente da correggere.
Da controllare
- 1 colonna di testo confronta ignorando maiuscole e minuscole nell'origine; Oracle confronta in modo esatto, quindi chiavi univoche e ricerche possono comportarsi diversamente. Usa una collation o un tipo di colonna che ignora maiuscole e minuscole nelle colonne che ne hanno bisogno.
- 2 viste, trigger, routine o eventi non sono convertiti; il report li elenca uno per uno. Ricreali a mano in Oracle.
Il tuo file viene convertito su questo computer e non viene mai caricato.
Altri esempi:
Cosa cambia da SQLite a Oracle
Ogni riga è una regola che il convertitore applica, con la riga del report che scrive quando la regola cambia qualcosa nei tuoi dati.
declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none)
il tipo in cui stanno tutti i valori della colonna
SQLite accetta qualsiasi valore in qualsiasi colonna, quindi il tipo dichiarato è un'indicazione: ogni colonna riceve il tipo in cui stanno tutti i suoi valori, e una colonna con valori misti ne mantiene il testo.
BOOLEAN, BOOL
NUMBER(1) con un CHECK di 0 e 1
Quando ogni valore è 0 o 1; una colonna che contiene anche altri valori li mantiene come numeri o testo.
TEXT, VARCHAR(n), CHAR(n), CLOB
VARCHAR2(n CHAR) quando ogni valore ci sta, altrimenti CLOB
SQLite non applica mai una lunghezza; una lunghezza dichiarata vale solo quando ogni valore ci sta.
TEXT and VARCHAR(n) longer than 4000 bytes
VARCHAR2(4000 CHAR) quando ogni valore sta in 4000 byte (750 caratteri in una chiave), altrimenti CLOB
Un VARCHAR2 contiene 4000 byte di default e Oracle non può indicizzare un CLOB, quindi il testo resta VARCHAR2 quando i valori ci stanno ed è un CLOB quando no.
Riga del report: text_as_lob
DECIMAL(p,s), NUMERIC
il tipo esatto quando ogni valore ci sta, altrimenti un double
SQLite li salva come interi o double; una precisione dichiarata vale solo quando i valori ci stanno.
BLOB, and columns holding bytes
BLOB
I byte restano byte; testo e numeri nella stessa colonna vengono mantenuti come i loro byte.
DATE, DATETIME, TIMESTAMP holding ISO 8601 text
DATE o TIMESTAMP(p), in base a ciò che contengono i valori
Quando ogni valore è una data o una data con ora; i numeri epoch e l'altro testo mantengono i loro valori così come sono.
JSON holding JSON text
CLOB
Quando ogni valore è un oggetto o un array JSON.
Infinity in REAL columns
mantenuto come BINARY_DOUBLE_INFINITY
I double di Oracle contengono l'infinito.
INTEGER PRIMARY KEY, AUTOINCREMENT
GENERATED BY DEFAULT ON NULL AS IDENTITY, che riparte dopo l'id più alto o dal valore di sqlite_sequence
Solo una colonna dichiarata esattamente INTEGER PRIMARY KEY è il rowid; ogni riga mantiene il suo id, e il contatore parte dopo l'id più alto mai assegnato.
COLLATE NOCASE
confronto esatto
Oracle confronta il testo in modo esatto salvo indicazione diversa; le colonne NOCASE smettono di ignorare le maiuscole.
Riga del report: case_insensitive_collation
generated columns
colonne virtuali
Oracle calcola le colonne generate solo in lettura; le colonne STORED diventano virtuali con gli stessi valori.
Riga del report: stored_as_virtual
generated columns with functions IntoSQL doesn't write, and the || operator
una colonna semplice
Una formula che non si può scrivere lascia una colonna semplice e una riga nel report; il dump non ha valori per le colonne generate.
Riga del report: generated_not_translated
defaults with functions IntoSQL doesn't write (strftime, randomblob)
nessun valore predefinito
Un valore predefinito che non si può scrivere viene omesso e segnalato; CURRENT_TIMESTAMP e datetime('now') vengono scritti.
Riga del report: default_not_translated
CHECK constraints
tradotti
Gli stessi CHECK, verificati mentre ogni riga si carica.
CHECK constraints with functions IntoSQL doesn't write
non creato
Un vincolo CHECK che non si può scrivere viene omesso e segnalato.
Riga del report: check_skipped
partial and expression indexes
non creato
IntoSQL scrive indici su colonne intere; ricrea gli altri dopo il caricamento.
Riga del report: index_skipped
foreign keys (unenforced unless PRAGMA foreign_keys=ON)
dopo i dati ENABLE NOVALIDATE, poi validata
SQLite verifica le chiavi esterne solo quando glielo si chiede, quindi le righe senza padre sono comuni: si caricano, e la chiave resta non controllata con un avviso invece di fermare il caricamento.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT
rimosso
Le chiavi esterne di Oracle agiscono solo in eliminazione, con CASCADE o SET NULL.
Riga del report: foreign_key_action_unsupported
empty strings and empty blobs
NULL
Oracle salva una stringa vuota come NULL, quindi un valore che era ' si rilegge come NULL. Il report li conta per colonna.
Riga del report: empty_string_null
foreign keys to tables the dump doesn't create
non creato
Una chiave non può riferirsi a una tabella che non c'è.
Riga del report: foreign_key_skipped
primary keys holding NULL, and NOT NULL columns with values that become NULL
NOT NULL rimosso
SQLite permette a una chiave primaria diversa dal rowid di contenere NULL; la colonna non può essere NOT NULL nella destinazione, altrimenti il caricamento si fermerebbe.
Riga del report: not_null_relaxed
views, triggers and virtual tables (FTS, R*Tree)
elencati nel report
Il loro codice è scritto nel linguaggio di SQLite, e le tabelle virtuali richiedono i moduli di SQLite; sono elencati perché tu li ricrei. Le loro tabelle interne non vengono copiate.
Riga del report: not_converted_objects
dumps without CREATE TABLE (--data-only)
tipi ricavati dai valori
Un dump di soli dati contiene solo righe, quindi i tipi vengono ricavati dai valori e le colonne sono numerate.
Riga del report: no_schema
expressions in INSERT values other than the text functions dumps write
NULL
unistr(), replace(), char() e || vengono valutati come li scrive la shell; le altre espressioni non si possono valutare senza un database.
Riga del report: expression_value
NUL characters in text
mantenuto
La shell sqlite3 e Python tagliano il testo a un carattere NUL quando lo esportano, quindi nel dump c'è solo ciò che lo precede.
text that isn't valid UTF-8
i byte errati come carattere di sostituzione
I dump scrivono quel testo come byte grezzi; lo script è UTF-8.
Riga del report: invalid_utf8_replaced
text decoded twice (ñ)
copiato così com'è
Il dump contiene esattamente questi caratteri, quindi vengono copiati; il report li segnala.
Riga del report: mojibake_suspected
| In SQLite | In Oracle | Riga del report |
|---|---|---|
| declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none) | il tipo in cui stanno tutti i valori della colonnaSQLite accetta qualsiasi valore in qualsiasi colonna, quindi il tipo dichiarato è un'indicazione: ogni colonna riceve il tipo in cui stanno tutti i suoi valori, e una colonna con valori misti ne mantiene il testo. | |
| BOOLEAN, BOOL | NUMBER(1) con un CHECK di 0 e 1Quando ogni valore è 0 o 1; una colonna che contiene anche altri valori li mantiene come numeri o testo. | |
| TEXT, VARCHAR(n), CHAR(n), CLOB | VARCHAR2(n CHAR) quando ogni valore ci sta, altrimenti CLOBSQLite non applica mai una lunghezza; una lunghezza dichiarata vale solo quando ogni valore ci sta. | |
| TEXT and VARCHAR(n) longer than 4000 bytes | VARCHAR2(4000 CHAR) quando ogni valore sta in 4000 byte (750 caratteri in una chiave), altrimenti CLOBUn VARCHAR2 contiene 4000 byte di default e Oracle non può indicizzare un CLOB, quindi il testo resta VARCHAR2 quando i valori ci stanno ed è un CLOB quando no. | text_as_lob |
| DECIMAL(p,s), NUMERIC | il tipo esatto quando ogni valore ci sta, altrimenti un doubleSQLite li salva come interi o double; una precisione dichiarata vale solo quando i valori ci stanno. | |
| BLOB, and columns holding bytes | BLOBI byte restano byte; testo e numeri nella stessa colonna vengono mantenuti come i loro byte. | |
| DATE, DATETIME, TIMESTAMP holding ISO 8601 text | DATE o TIMESTAMP(p), in base a ciò che contengono i valoriQuando ogni valore è una data o una data con ora; i numeri epoch e l'altro testo mantengono i loro valori così come sono. | |
| JSON holding JSON text | CLOBQuando ogni valore è un oggetto o un array JSON. | |
| Infinity in REAL columns | mantenuto come BINARY_DOUBLE_INFINITYI double di Oracle contengono l'infinito. | |
| INTEGER PRIMARY KEY, AUTOINCREMENT | GENERATED BY DEFAULT ON NULL AS IDENTITY, che riparte dopo l'id più alto o dal valore di sqlite_sequenceSolo una colonna dichiarata esattamente INTEGER PRIMARY KEY è il rowid; ogni riga mantiene il suo id, e il contatore parte dopo l'id più alto mai assegnato. | |
| COLLATE NOCASE | confronto esattoOracle confronta il testo in modo esatto salvo indicazione diversa; le colonne NOCASE smettono di ignorare le maiuscole. | case_insensitive_collation |
| generated columns | colonne virtualiOracle calcola le colonne generate solo in lettura; le colonne STORED diventano virtuali con gli stessi valori. | stored_as_virtual |
| generated columns with functions IntoSQL doesn't write, and the || operator | una colonna sempliceUna formula che non si può scrivere lascia una colonna semplice e una riga nel report; il dump non ha valori per le colonne generate. | generated_not_translated |
| defaults with functions IntoSQL doesn't write (strftime, randomblob) | nessun valore predefinitoUn valore predefinito che non si può scrivere viene omesso e segnalato; CURRENT_TIMESTAMP e datetime('now') vengono scritti. | default_not_translated |
| CHECK constraints | tradottiGli stessi CHECK, verificati mentre ogni riga si carica. | |
| CHECK constraints with functions IntoSQL doesn't write | non creatoUn vincolo CHECK che non si può scrivere viene omesso e segnalato. | check_skipped |
| partial and expression indexes | non creatoIntoSQL scrive indici su colonne intere; ricrea gli altri dopo il caricamento. | index_skipped |
| foreign keys (unenforced unless PRAGMA foreign_keys=ON) | dopo i dati ENABLE NOVALIDATE, poi validataSQLite verifica le chiavi esterne solo quando glielo si chiede, quindi le righe senza padre sono comuni: si caricano, e la chiave resta non controllata con un avviso invece di fermare il caricamento. | |
| ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT | rimossoLe chiavi esterne di Oracle agiscono solo in eliminazione, con CASCADE o SET NULL. | foreign_key_action_unsupported |
| empty strings and empty blobs | NULLOracle salva una stringa vuota come NULL, quindi un valore che era ' si rilegge come NULL. Il report li conta per colonna. | empty_string_null |
| foreign keys to tables the dump doesn't create | non creatoUna chiave non può riferirsi a una tabella che non c'è. | foreign_key_skipped |
| primary keys holding NULL, and NOT NULL columns with values that become NULL | NOT NULL rimossoSQLite permette a una chiave primaria diversa dal rowid di contenere NULL; la colonna non può essere NOT NULL nella destinazione, altrimenti il caricamento si fermerebbe. | not_null_relaxed |
| views, triggers and virtual tables (FTS, R*Tree) | elencati nel reportIl loro codice è scritto nel linguaggio di SQLite, e le tabelle virtuali richiedono i moduli di SQLite; sono elencati perché tu li ricrei. Le loro tabelle interne non vengono copiate. | not_converted_objects |
| dumps without CREATE TABLE (--data-only) | tipi ricavati dai valoriUn dump di soli dati contiene solo righe, quindi i tipi vengono ricavati dai valori e le colonne sono numerate. | no_schema |
| expressions in INSERT values other than the text functions dumps write | NULLunistr(), replace(), char() e || vengono valutati come li scrive la shell; le altre espressioni non si possono valutare senza un database. | expression_value |
| NUL characters in text | mantenutoLa shell sqlite3 e Python tagliano il testo a un carattere NUL quando lo esportano, quindi nel dump c'è solo ciò che lo precede. | |
| text that isn't valid UTF-8 | i byte errati come carattere di sostituzioneI dump scrivono quel testo come byte grezzi; lo script è UTF-8. | invalid_utf8_replaced |
| text decoded twice (ñ) | copiato così com'èIl dump contiene esattamente questi caratteri, quindi vengono copiati; il report li segnala. | mojibake_suspected |
Carica lo script in Oracle
Lo script crea le tabelle, copia le righe, poi aggiunge chiavi, indici e chiavi esterne, così si carica in fretta e si ferma al primo errore.
NLS_LANG=.AL32UTF8 sqlplus -S -L user@//localhost/mydb @sqlite.oracle.sqlLe chiavi esterne vengono aggiunte ENABLE NOVALIDATE, così le nuove righe sono controllate subito, e poi validate. Se una riga vecchia punta a una riga che non esiste, lo script dice quale vincolo e lo lascia non validato, invece di fallire a metà.
Per un dump grande, esegui SQL*Plus sulla stessa macchina del database. Lo script fa il commit ogni 100 righe. L'utente che lo esegue ha bisogno di CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER e CREATE PROCEDURE, e di una quota sul suo tablespace.
Fai il dump di SQLite per il miglior risultato
Il convertitore legge ciò che il dump contiene. Con queste opzioni il dump conserva più dei tuoi dati:
- Il file del database si converte così com'è, letto pagina per pagina nel browser. Chiudi prima l'app che ci scrive, così nessuna modifica resta indietro nel suo file -wal.
- sqlite3 app.db .dump > app.sql scrive lo stesso database come SQL, che si converte anch'esso, come .sql o .sql.gz.
- DB Browser for SQLite scrive quel SQL con File, Export, Database to SQL file, e così fa iterdump() di Python.
Cosa non viene convertito
Viste e trigger sono scritti nel linguaggio di SQLite. Sono elencati per nome nel report, mai rimossi in silenzio, così puoi riscriverli per Oracle. Anche le tabelle virtuali, come FTS5 e R*Tree, sono elencate, e le loro tabelle interne vengono escluse.
Domande sulla conversione da SQLite a Oracle
Non trovi la risposta? Scrivici dalla pagina dei contatti e ti risponde una persona. Pagina dei contatti
Il mio dump viene caricato?
No. Il convertitore funziona nel tuo browser e legge il dump dal tuo disco a pezzi, quindi non lascia mai il tuo computer. Anche l'app desktop e la riga di comando convertono sul tuo computer.
Quanto può essere grande il dump?
Il convertitore non tiene mai l'intero dump in memoria: legge il file due volte, per intervalli, e scrive lo script man mano. I dump di più gigabyte si convertono nel browser, nell'app desktop e con la riga di comando.
Posso convertire direttamente il file .db?
Sì. Trascina il file .db, .sqlite o .sqlite3: viene letto nel browser e mai caricato. Il testo con caratteri NUL e ogni cifra di un double arrivano come sono salvati, cosa che un .dump può troncare.
Da quali versioni di SQLite può provenire il dump?
File di database da SQLite 3.0 in poi, in UTF-8 o UTF-16, e dump del .dump della shell sqlite3 o di iterdump() di Python. Ogni file e dump di test viene da sqlite3 dalla 3.31 alla 3.54, tabelle STRICT e WITHOUT ROWID incluse, ed è confrontato con la sorgente cella per cella.
Come vengono decisi i tipi di colonna se SQLite non li applica?
Il tipo dichiarato è un'indicazione e decidono i valori: una colonna diventa NUMBER, BINARY_DOUBLE, DATE, TIMESTAMP, BLOB, VARCHAR2 o CLOB quando ogni valore ci sta. Le stringhe vuote diventano NULL, come le salva Oracle, e il report le conta.
INTEGER PRIMARY KEY e AUTOINCREMENT vengono mantenuti?
Sì. Una INTEGER PRIMARY KEY diventa una colonna identity, ogni riga mantiene il suo id, e l'id successivo riparte dopo il più alto, o dopo il valore di sqlite_sequence con AUTOINCREMENT.
E viste e trigger?
Sono elencati per nome nel report e non vengono convertiti, perché ogni database li scrive nel proprio linguaggio.
Su quali versioni di Oracle si carica lo script?
Oracle 19c e successive. Ogni dump di test si carica su 21c e 23ai, fermandosi al primo errore se qualcosa va storto.