Naar de inhoud
IntoSQL-startpagina

SQLite omzetten naar Oracle

Zet een SQLite-databasebestand (.db, .sqlite, .sqlite3) neer of de SQL die .dump van sqlite3 schrijft, en download een Oracle-script met dezelfde tabellen, sleutels, indexen en data. Elke kolom krijgt het type waarin zijn waarden passen, en elke waarde die Oracle niet ongewijzigd kan bevatten, staat in het rapport.

Je bestand
sqlshop_2024_sqlite.sqlVoorbeeldbestand, 3,4 kB
Je database

18 rijen geconverteerd, geen correcties, geen afgewezen

Tonen

Tabellen in shop_2024_sqlite.sqlSQLite-dump · geschreven door sqlite3 · utf-8

  • customersgeschreven als CUSTOMERS8 rijen
    7 kolommen
    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
  • ordersgeschreven als ORDERS10 rijen
    9 kolommen
    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

Niet geconverteerd

  • Weergave order_totals
  • Trigger orders_shipped

Elke database schrijft deze in een eigen taal. Herschrijf ze voor 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;

Correcties

Er hoefde niets gecorrigeerd te worden.

Na te kijken

  • 1 tekstkolom vergelijkt in de bron zonder op hoofdletters te letten; Oracle vergelijkt exact, dus unieke sleutels en zoekopdrachten kunnen anders werken. Gebruik een collation of kolomtype dat hoofdletters negeert voor de kolommen die dat nodig hebben.
  • 2 weergaven, triggers, routines of gebeurtenissen zijn niet geconverteerd; het rapport noemt ze allemaal. Maak ze met de hand opnieuw aan in Oracle.

Je bestand wordt op deze computer omgezet en nooit geüpload.

Andere voorbeelden:

Wat er verandert van SQLite naar Oracle

Elke rij is een regel die de converter toepast, met de rapportregel die hij schrijft als de regel iets in je data verandert.

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

    het type waarin elke waarde in de kolom past

    SQLite bewaart elke waarde in elke kolom, dus het gedeclareerde type is een hint: elke kolom krijgt het type waarin al zijn waarden passen, en een kolom met gemengde waarden behoudt hun tekst.

  • BOOLEAN, BOOL

    NUMBER(1) met een CHECK op 0 en 1

    Als elke waarde 0 of 1 is; een kolom die ook andere waarden bevat, behoudt ze als getallen of tekst.

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

    VARCHAR2(n CHAR) als elke waarde past, anders CLOB

    SQLite dwingt nooit een lengte af; een gedeclareerde lengte geldt alleen als elke waarde erin past.

  • TEXT and VARCHAR(n) longer than 4000 bytes

    VARCHAR2(4000 CHAR) als elke waarde in 4000 bytes past (750 tekens in een sleutel), anders CLOB

    Een VARCHAR2 bevat standaard 4000 bytes en Oracle kan een CLOB niet indexeren, dus tekst blijft VARCHAR2 als de waarden passen en wordt CLOB als ze dat niet doen.

    Rapportregel: text_as_lob

  • DECIMAL(p,s), NUMERIC

    het exacte type als elke waarde erin past, anders een double

    SQLite slaat deze op als gehele getallen of doubles; een gedeclareerde precisie geldt alleen als de waarden erin passen.

  • BLOB, and columns holding bytes

    BLOB

    Bytes blijven bytes; tekst en getallen in dezelfde kolom blijven behouden als hun bytes.

  • DATE, DATETIME, TIMESTAMP holding ISO 8601 text

    DATE of TIMESTAMP(p), afhankelijk van wat de waarden bevatten

    Als elke waarde een datum of een datum met tijd is; epoch-getallen en andere tekst behouden hun waarden ongewijzigd.

  • JSON holding JSON text

    CLOB

    Als elke waarde een JSON-object of -array is.

  • Infinity in REAL columns

    behouden als BINARY_DOUBLE_INFINITY

    Doubles in Oracle kunnen oneindig bevatten.

  • INTEGER PRIMARY KEY, AUTOINCREMENT

    GENERATED BY DEFAULT ON NULL AS IDENTITY, verdergaand na het hoogste id of de waarde in sqlite_sequence

    Alleen een kolom die precies als INTEGER PRIMARY KEY is gedeclareerd, is de rowid; elke rij behoudt zijn id, en de teller begint na het hoogste id dat ooit is uitgegeven.

  • COLLATE NOCASE

    exacte vergelijking

    Oracle vergelijkt tekst exact, tenzij anders aangegeven; NOCASE-kolommen negeren hoofdletters niet langer.

    Rapportregel: case_insensitive_collation

  • generated columns

    virtuele kolommen

    Oracle berekent gegenereerde kolommen alleen bij het lezen; STORED-kolommen worden virtueel met dezelfde waarden.

    Rapportregel: stored_as_virtual

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

    een gewone kolom

    Een formule die niet kan worden geschreven, levert een gewone kolom en een regel in het rapport op; de dump bevat geen waarden voor gegenereerde kolommen.

    Rapportregel: generated_not_translated

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

    geen standaardwaarde

    Een standaardwaarde die niet kan worden geschreven, wordt weggelaten en gemeld; CURRENT_TIMESTAMP en datetime('now') worden wel geschreven.

    Rapportregel: default_not_translated

  • CHECK constraints

    vertaald

    Dezelfde checks, getest terwijl elke rij laadt.

  • CHECK constraints with functions IntoSQL doesn't write

    niet aangemaakt

    Een check die niet kan worden geschreven, wordt weggelaten en gemeld.

    Rapportregel: check_skipped

  • partial and expression indexes

    niet aangemaakt

    IntoSQL schrijft indexen op hele kolommen; maak de andere na het laden opnieuw aan.

    Rapportregel: index_skipped

  • foreign keys (unenforced unless PRAGMA foreign_keys=ON)

    na de data ENABLE NOVALIDATE, daarna gevalideerd

    SQLite controleert refererende sleutels alleen als dat gevraagd wordt, dus rijen zonder ouder komen vaak voor: ze laden, en de sleutel blijft ongecontroleerd met een waarschuwing, in plaats van het laden te stoppen.

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

    weggelaten

    Refererende sleutels in Oracle werken alleen bij verwijderen, met CASCADE of SET NULL.

    Rapportregel: foreign_key_action_unsupported

  • empty strings and empty blobs

    NULL

    Oracle slaat een lege string op als NULL, dus een waarde die ' was, wordt teruggelezen als NULL. Het rapport telt ze per kolom.

    Rapportregel: empty_string_null

  • foreign keys to tables the dump doesn't create

    niet aangemaakt

    Een sleutel kan niet verwijzen naar een tabel die er niet is.

    Rapportregel: foreign_key_skipped

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

    NOT NULL weggelaten

    SQLite staat NULL toe in een primaire sleutel die niet de rowid is; de kolom kan in het doel niet NOT NULL zijn, anders zou het laden stoppen.

    Rapportregel: not_null_relaxed

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

    vermeld in het rapport

    Hun code is geschreven in de eigen taal van SQLite, en virtuele tabellen hebben de modules van SQLite nodig; ze worden vermeld zodat je ze opnieuw kunt maken. Hun interne tabellen worden niet gekopieerd.

    Rapportregel: not_converted_objects

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

    typen afgeleid uit de waarden

    Een dump met alleen data bevat alleen rijen, dus de typen komen uit de waarden en de kolommen worden genummerd.

    Rapportregel: no_schema

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

    NULL

    unistr(), replace(), char() en || worden geëvalueerd zoals de shell ze schrijft; andere expressies kunnen zonder database niet worden geëvalueerd.

    Rapportregel: expression_value

  • NUL characters in text

    behouden

    De sqlite3-shell en Python kappen tekst af bij een NUL-teken als ze hem dumpen, dus alleen wat ervoor staat, zit in de dump.

  • text that isn't valid UTF-8

    de foute bytes als het vervangingsteken

    Dumps schrijven zulke tekst als ruwe bytes; het script is UTF-8.

    Rapportregel: invalid_utf8_replaced

  • text decoded twice (ñ)

    ongewijzigd gekopieerd

    De dump bevat precies deze tekens, dus ze worden gekopieerd; het rapport wijst ze aan.

    Rapportregel: mojibake_suspected

In SQLiteIn OracleRapportregel
declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none)het type waarin elke waarde in de kolom pastSQLite bewaart elke waarde in elke kolom, dus het gedeclareerde type is een hint: elke kolom krijgt het type waarin al zijn waarden passen, en een kolom met gemengde waarden behoudt hun tekst.
BOOLEAN, BOOLNUMBER(1) met een CHECK op 0 en 1Als elke waarde 0 of 1 is; een kolom die ook andere waarden bevat, behoudt ze als getallen of tekst.
TEXT, VARCHAR(n), CHAR(n), CLOBVARCHAR2(n CHAR) als elke waarde past, anders CLOBSQLite dwingt nooit een lengte af; een gedeclareerde lengte geldt alleen als elke waarde erin past.
TEXT and VARCHAR(n) longer than 4000 bytesVARCHAR2(4000 CHAR) als elke waarde in 4000 bytes past (750 tekens in een sleutel), anders CLOBEen VARCHAR2 bevat standaard 4000 bytes en Oracle kan een CLOB niet indexeren, dus tekst blijft VARCHAR2 als de waarden passen en wordt CLOB als ze dat niet doen.text_as_lob
DECIMAL(p,s), NUMERIChet exacte type als elke waarde erin past, anders een doubleSQLite slaat deze op als gehele getallen of doubles; een gedeclareerde precisie geldt alleen als de waarden erin passen.
BLOB, and columns holding bytesBLOBBytes blijven bytes; tekst en getallen in dezelfde kolom blijven behouden als hun bytes.
DATE, DATETIME, TIMESTAMP holding ISO 8601 textDATE of TIMESTAMP(p), afhankelijk van wat de waarden bevattenAls elke waarde een datum of een datum met tijd is; epoch-getallen en andere tekst behouden hun waarden ongewijzigd.
JSON holding JSON textCLOBAls elke waarde een JSON-object of -array is.
Infinity in REAL columnsbehouden als BINARY_DOUBLE_INFINITYDoubles in Oracle kunnen oneindig bevatten.
INTEGER PRIMARY KEY, AUTOINCREMENTGENERATED BY DEFAULT ON NULL AS IDENTITY, verdergaand na het hoogste id of de waarde in sqlite_sequenceAlleen een kolom die precies als INTEGER PRIMARY KEY is gedeclareerd, is de rowid; elke rij behoudt zijn id, en de teller begint na het hoogste id dat ooit is uitgegeven.
COLLATE NOCASEexacte vergelijkingOracle vergelijkt tekst exact, tenzij anders aangegeven; NOCASE-kolommen negeren hoofdletters niet langer.case_insensitive_collation
generated columnsvirtuele kolommenOracle berekent gegenereerde kolommen alleen bij het lezen; STORED-kolommen worden virtueel met dezelfde waarden.stored_as_virtual
generated columns with functions IntoSQL doesn't write, and the || operatoreen gewone kolomEen formule die niet kan worden geschreven, levert een gewone kolom en een regel in het rapport op; de dump bevat geen waarden voor gegenereerde kolommen.generated_not_translated
defaults with functions IntoSQL doesn't write (strftime, randomblob)geen standaardwaardeEen standaardwaarde die niet kan worden geschreven, wordt weggelaten en gemeld; CURRENT_TIMESTAMP en datetime('now') worden wel geschreven.default_not_translated
CHECK constraintsvertaaldDezelfde checks, getest terwijl elke rij laadt.
CHECK constraints with functions IntoSQL doesn't writeniet aangemaaktEen check die niet kan worden geschreven, wordt weggelaten en gemeld.check_skipped
partial and expression indexesniet aangemaaktIntoSQL schrijft indexen op hele kolommen; maak de andere na het laden opnieuw aan.index_skipped
foreign keys (unenforced unless PRAGMA foreign_keys=ON)na de data ENABLE NOVALIDATE, daarna gevalideerdSQLite controleert refererende sleutels alleen als dat gevraagd wordt, dus rijen zonder ouder komen vaak voor: ze laden, en de sleutel blijft ongecontroleerd met een waarschuwing, in plaats van het laden te stoppen.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULTweggelatenRefererende sleutels in Oracle werken alleen bij verwijderen, met CASCADE of SET NULL.foreign_key_action_unsupported
empty strings and empty blobsNULLOracle slaat een lege string op als NULL, dus een waarde die ' was, wordt teruggelezen als NULL. Het rapport telt ze per kolom.empty_string_null
foreign keys to tables the dump doesn't createniet aangemaaktEen sleutel kan niet verwijzen naar een tabel die er niet is.foreign_key_skipped
primary keys holding NULL, and NOT NULL columns with values that become NULLNOT NULL weggelatenSQLite staat NULL toe in een primaire sleutel die niet de rowid is; de kolom kan in het doel niet NOT NULL zijn, anders zou het laden stoppen.not_null_relaxed
views, triggers and virtual tables (FTS, R*Tree)vermeld in het rapportHun code is geschreven in de eigen taal van SQLite, en virtuele tabellen hebben de modules van SQLite nodig; ze worden vermeld zodat je ze opnieuw kunt maken. Hun interne tabellen worden niet gekopieerd.not_converted_objects
dumps without CREATE TABLE (--data-only)typen afgeleid uit de waardenEen dump met alleen data bevat alleen rijen, dus de typen komen uit de waarden en de kolommen worden genummerd.no_schema
expressions in INSERT values other than the text functions dumps writeNULLunistr(), replace(), char() en || worden geëvalueerd zoals de shell ze schrijft; andere expressies kunnen zonder database niet worden geëvalueerd.expression_value
NUL characters in textbehoudenDe sqlite3-shell en Python kappen tekst af bij een NUL-teken als ze hem dumpen, dus alleen wat ervoor staat, zit in de dump.
text that isn't valid UTF-8de foute bytes als het vervangingstekenDumps schrijven zulke tekst als ruwe bytes; het script is UTF-8.invalid_utf8_replaced
text decoded twice (ñ)ongewijzigd gekopieerdDe dump bevat precies deze tekens, dus ze worden gekopieerd; het rapport wijst ze aan.mojibake_suspected

Het script in Oracle laden

Het script maakt de tabellen aan, kopieert de rijen en voegt daarna sleutels, indexen en refererende sleutels toe, zodat het snel laadt en bij de eerste fout stopt.

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

Refererende sleutels worden toegevoegd met ENABLE NOVALIDATE, zodat nieuwe rijen meteen worden gecontroleerd, en daarna gevalideerd. Verwijst een oude rij naar een rij die niet bestaat, dan vertelt het script welke constraint het is en laat het die ongevalideerd, in plaats van halverwege te mislukken.

Voer bij een grote dump SQL*Plus uit op dezelfde machine als de database. Het script commit elke 100 rijen. De gebruiker die het uitvoert, heeft CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER en CREATE PROCEDURE nodig, en quota op zijn tablespace.

Een dump van SQLite maken voor het beste resultaat

De converter leest wat de dump bevat. Met deze opties blijft er meer van je data in staan:

  • Het databasebestand zelf wordt ongewijzigd geconverteerd, pagina voor pagina gelezen in je browser. Sluit eerst de app die erin schrijft, zodat er geen wijziging achterblijft in het -wal-bestand.
  • sqlite3 app.db .dump > app.sql schrijft dezelfde database als SQL, die ook wordt geconverteerd, als .sql of .sql.gz.
  • DB Browser for SQLite schrijft die SQL met File, Export, Database to SQL file, en iterdump() in Python ook.

Wat niet wordt geconverteerd

Weergaven en triggers zijn geschreven in de eigen taal van SQLite. Ze staan op naam in het rapport en worden nooit stilletjes weggelaten, zodat je ze kunt herschrijven voor Oracle. Virtuele tabellen, zoals FTS5 en R*Tree, worden ook vermeld, en hun schaduwtabellen worden weggelaten.

Vragen over SQLite naar Oracle

Staat je vraag er niet bij? Schrijf ons via de contactpagina en een mens antwoordt. Contactpagina

Wordt mijn dump geüpload?

Nee. De converter draait in je browser en leest de dump in delen van je schijf, dus hij verlaat je computer nooit. De desktopapp en de opdrachtregel converteren ook op je computer.

Hoe groot mag de dump zijn?

De converter houdt nooit de hele dump in het geheugen: hij leest het bestand twee keer, in bereiken, en schrijft het script gaandeweg. Dumps van meerdere gigabytes worden geconverteerd in de browser, in de desktopapp en met de opdrachtregel.

Kan ik het .db-bestand zelf converteren?

Ja. Zet het .db-, .sqlite- of .sqlite3-bestand neer: het wordt in je browser gelezen en nooit geüpload. Tekst met NUL-tekens en elk cijfer van een double komen aan zoals ze zijn opgeslagen, wat een .dump kan afkappen.

Van welke SQLite-versies kan de dump komen?

Databasebestanden vanaf SQLite 3.0, in UTF-8 of UTF-16, en dumps van .dump in de sqlite3-shell of van iterdump() in Python. Elk testbestand en elke testdump komt van sqlite3 3.31 tot en met 3.54, STRICT- en WITHOUT ROWID-tabellen inbegrepen, en wordt cel voor cel met zijn bron vergeleken.

Hoe worden kolomtypen bepaald als SQLite ze niet afdwingt?

Het gedeclareerde type is een hint en de waarden beslissen: een kolom wordt NUMBER, BINARY_DOUBLE, DATE, TIMESTAMP, BLOB, VARCHAR2 of CLOB als elke waarde erin past. Lege strings worden NULL, zoals Oracle ze opslaat, en het rapport telt ze.

Blijven INTEGER PRIMARY KEY en AUTOINCREMENT behouden?

Ja. Een INTEGER PRIMARY KEY wordt een identity-kolom, elke rij behoudt zijn id, en het volgende id gaat verder na het hoogste, of na de waarde in sqlite_sequence bij AUTOINCREMENT.

En weergaven en triggers?

Ze staan op naam in het rapport en worden niet geconverteerd, omdat elke database ze in een eigen taal schrijft.

Op welke Oracle-versies laadt het script?

Oracle 19c en later. Elke testdump laadt op 21c en 23ai en stopt bij de eerste fout als er iets misgaat.