Przenieś eksport Oracle do starszej lub nowszej wersji Oracle
Upuść plik .sql zapisany przez Database Export w SQL Developer lub przez SQLcl, z tabelami i instrukcjami Insert, i pobierz skrypt, który ładuje się na Oracle 19c i nowszych. NUMBER, DATE, TIMESTAMP, LOB, kolumny identity i sekwencje zostają bez zmian, XMLTYPE i JSON zachowują tekst w CLOB, a każda zmiana jest wymieniona w raporcie.
18 wierszy przekonwertowanych, bez poprawek, brak odrzuconych
Tabele w pliku shop_2024_oracle.sqlZrzut Oracle · zapisany przez SQL Developer · utf-8
customerszapisana jako CUSTOMERS8 wierszy
7 kolumn ID NUMBER(10,0) not null NAME VARCHAR2(100 CHAR) not null EMAIL VARCHAR2(150 CHAR) not null COUNTRY CHAR(2 BYTE) not null IS_ACTIVE NUMBER(1,0) not null SIGNED_UP DATE CREATED_AT TIMESTAMP(0) not null orderszapisana jako ORDERS10 wierszy
9 kolumn ID NUMBER(10,0) not null CUSTOMER_ID NUMBER(10,0) not null INVOICE NUMBER(10,0) STATUS VARCHAR2(10 CHAR) not null TOTAL NUMBER(10,2) not null ITEMS NUMBER(5,0) not null ORDERED_AT DATE not null SHIPPED_AT DATE NOTE VARCHAR2(255 CHAR)
-- Written by IntoSQL from a Oracle 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 SEQUENCE "INVOICE_NUMBERS" START WITH 1020 INCREMENT BY 1 MINVALUE 1;
CREATE TABLE "CUSTOMERS" (
"ID" NUMBER(10,0) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1),
"NAME" VARCHAR2(100 CHAR) NOT NULL,
"EMAIL" VARCHAR2(150 CHAR) NOT NULL,
"COUNTRY" CHAR(2 BYTE) DEFAULT 'US' NOT NULL,
"IS_ACTIVE" NUMBER(1,0) DEFAULT 1 NOT NULL,
"SIGNED_UP" DATE,
"CREATED_AT" TIMESTAMP(0) DEFAULT LOCALTIMESTAMP NOT NULL,
CONSTRAINT "CHECK1" CHECK ("IS_ACTIVE" IN (0, 1))
);
CREATE TABLE "ORDERS" (
"ID" NUMBER(10,0) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1),
"CUSTOMER_ID" NUMBER(10,0) NOT NULL,
"INVOICE" NUMBER(10,0) DEFAULT ("INVOICE_NUMBERS".NEXTVAL),
"STATUS" VARCHAR2(10 CHAR) DEFAULT 'pending' NOT NULL,
"TOTAL" NUMBER(10,2) NOT NULL,
"ITEMS" NUMBER(5,0) DEFAULT 1 NOT NULL,
"ORDERED_AT" DATE NOT NULL,
"SHIPPED_AT" DATE,
"NOTE" VARCHAR2(255 CHAR),
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,
TIMESTAMP '2023-01-15 00:00:00',
TIMESTAMP '2023-01-15 10:24:00.000000000'
);
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,
TIMESTAMP '2023-02-03 00:00:00',
TIMESTAMP '2023-02-03 08:11:42.000000000'
);
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,
TIMESTAMP '2023-03-21 00:00:00',
TIMESTAMP '2023-03-21 19:05:17.000000000'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
4,
'李雷',
'lilei@example.cn',
'CN',
1,
TIMESTAMP '2023-05-09 00:00:00',
TIMESTAMP '2023-05-09 02:40:00.000000000'
);
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.000000000'
);
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,
TIMESTAMP '2024-01-02 00:00:00',
TIMESTAMP '2024-01-02 09:30:00.000000000'
);
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,
TIMESTAMP '2024-02-29 00:00:00',
TIMESTAMP '2024-02-29 23:59:59.000000000'
);
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,
TIMESTAMP '2024-04-12 00:00:00',
TIMESTAMP '2024-04-12 12:12:12.000000000'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
1,
1,
1000,
'shipped',
129.9,
3,
TIMESTAMP '2024-03-01 10:00:00',
TIMESTAMP '2024-03-02 16:30:00',
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
2,
2,
1001,
'paid',
54,
1,
TIMESTAMP '2024-03-02 11:15:00',
NULL,
'Gift wrap 🎁'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
3,
1,
1002,
'cancelled',
12.5,
1,
TIMESTAMP '2024-03-03 09:45:00',
NULL,
'Customer changed their mind'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
4,
4,
1003,
'shipped',
980,
12,
TIMESTAMP '2024-03-05 02:10:00',
TIMESTAMP '2024-03-07 08:00:00',
'请小心轻放'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
5,
5,
1004,
'pending',
45.75,
2,
TIMESTAMP '2024-03-08 17:20:00',
NULL,
'Leave at the door; ring twice'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
6,
6,
1005,
'shipped',
310.4,
5,
TIMESTAMP '2024-03-10 13:00:00',
TIMESTAMP '2024-03-11 09:00:00',
'Fragile: "glass"'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
7,
8,
1006,
'paid',
76.2,
2,
TIMESTAMP '2024-03-11 18:45:00',
NULL,
NULL
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
8,
2,
1007,
'paid',
19.99,
1,
TIMESTAMP '2024-03-12 08:00:00',
NULL,
'Paid at the counter'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
9,
3,
1008,
'shipped',
64,
2,
TIMESTAMP '2024-03-14 15:30:00',
NULL,
'Shipping date never recorded'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"INVOICE",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE"
) VALUES (
10,
7,
1009,
'paid',
1499,
1,
TIMESTAMP '2024-03-15 21:05:00',
NULL,
'C:\Users\ravi\invoice.pdf'
);
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_CUSTOMERS_EMAIL_UK" UNIQUE ("EMAIL");
ALTER TABLE "ORDERS" ADD CONSTRAINT "PK_ORDERS" PRIMARY KEY ("ID");
CREATE INDEX "IX_ORDERS_ORDERS_STATUS_DATE_IX" ON "ORDERS" ("STATUS", "ORDERED_AT");
ALTER TABLE "ORDERS" ADD CONSTRAINT "ORDERS_CUSTOMER_FK" FOREIGN KEY ("CUSTOMER_ID") REFERENCES "CUSTOMERS" ("ID") ENABLE NOVALIDATE;
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "ORDERS" ENABLE VALIDATE CONSTRAINT "ORDERS_CUSTOMER_FK"';
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Foreign key ' || '"ORDERS_CUSTOMER_FK"' || ' 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 < 1 THEN
next_id := 1;
END IF;
EXECUTE IMMEDIATE 'ALTER TABLE "CUSTOMERS" MODIFY ("ID" GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH ' || next_id || '))';
END;
/
COMMENT ON TABLE "CUSTOMERS" IS 'People who bought at least once';
DECLARE
next_id NUMBER;
BEGIN
SELECT NVL(MAX("ID"), 0) + 1 INTO next_id FROM "ORDERS";
IF next_id < 1 THEN
next_id := 1;
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;
Poprawki
Nic nie wymagało poprawek.
Plik jest konwertowany na tym komputerze i nigdy nie jest wysyłany.
Inne przykłady:
Co się zmienia między plikiem a skryptem
Każdy wiersz to reguła stosowana przez konwerter, z wpisem, który dodaje do raportu, gdy reguła coś zmienia w twoich danych.
BOOLEAN (23ai)
BOOLEAN na 23ai, w przeciwnym razie NUMBER(1) z CHECK 0 i 1
TRUE i FALSE pozostają true i false.
VARCHAR2(n BYTE|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONG
te same typy, z długościami w BYTE lub CHAR
Te same typy tekstowe; LONG staje się CLOB, który preferuje każda wersja od 8.
VARCHAR2 and NVARCHAR2 past what the target's own types hold
VARCHAR2(4000 CHAR), gdy każda wartość mieści się w 4000 bajtach, w przeciwnym razie CLOB
VARCHAR2 mieści domyślnie 4000 bajtów, a Oracle nie indeksuje CLOB, więc tekst zostaje VARCHAR2, gdy jego wartości się mieszczą, a CLOB, gdy nie.
Wpis w raporcie: text_as_lob
NUMBER, NUMBER(p,s), FLOAT(b)
te same typy NUMBER
Te same typy NUMBER i FLOAT, ze wszystkimi cyframi.
INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECOND
te same typy INTERVAL
Te same interwały.
DATE, TIMESTAMP(p)
DATE i TIMESTAMP(p), jak zadeklarowano
Te same typy, więc każda data zachowuje godzinę z dokładnością do sekundy.
TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE
te same typy
Oracle przechowuje przesunięcia od -12:00 do +14:00; wartość z przesunięciem poza -12:00 jest zapisywana w UTC, ten sam moment.
JSON (21c), and CLOB holding JSON
JSON od 21c, w przeciwnym razie CLOB
Te same wartości JSON; SQL NULL zapisany przez eksport jako 'null' pozostaje NULL.
BLOB, RAW(n), LONG RAW
te same typy; LONG RAW jako BLOB
Bajty pozostają bajtami.
ROWID, UROWID, XMLTYPE, SDO_GEOMETRY
CLOB z ich tekstem
XMLTYPE, ROWID i UROWID zachowują swój tekst w CLOB, więc skrypt ładuje się na każdej wersji od 19c.
Wpis w raporcie: type_replaced
collations that ignore case (BINARY_CI)
dokładne porównanie
Porównywania kolumn nie są zapisywane, więc kolumna, która ignorowała wielkość liter (BINARY_CI), teraz odróżnia Ana od ana.
Wpis w raporcie: case_insensitive_collation
identity columns, and a sequence a BEFORE INSERT trigger assigns
GENERATED BY DEFAULT ON NULL AS IDENTITY, kontynuowane po najwyższym id
Skopiowane id ładują się bez zmian, a licznik idzie dalej od najwyższego z nich. Kolumna, którą wyzwalacz wypełnia z sekwencji (sposób sprzed 12c), też staje się kolumną identity.
identity columns the target can't count
zwykła liczba całkowita
Oracle liczy jedną kolumnę identity na tabelę; każda inna zachowuje wartości bez licznika.
Wpis w raporcie: counter_dropped
CREATE SEQUENCE
CREATE SEQUENCE z tymi samymi opcjami
Eksport zapisuje, dokąd doszła sekwencja, jako jej START WITH, więc kontynuuje ona od tego miejsca.
virtual columns (GENERATED ALWAYS AS ... VIRTUAL)
kolumny wirtualne
Te same kolumny wirtualne.
Wpis w raporcie: stored_as_virtual
virtual columns with functions IntoSQL doesn't write, and the || operator
zwykła kolumna
Formuła, której nie da się zapisać dla Oracle, zostawia zwykłą kolumnę i wpis w raporcie; wartości, które eksport zapisał dla kolumn wirtualnych, są pomijane, a Oracle nie może ich obliczyć.
Wpis w raporcie: generated_not_translated
defaults with functions IntoSQL doesn't write (SYS_GUID(), ||)
brak wartości domyślnej
Wartość domyślna, której nie da się zapisać, jest pomijana i zgłaszana w raporcie.
Wpis w raporcie: default_not_translated
CHECK constraints
przetłumaczone
Te same ograniczenia CHECK, sprawdzane przy ładowaniu każdego wiersza.
CHECK constraints with functions IntoSQL doesn't write
nie jest tworzone
Ograniczenie CHECK, którego nie da się zapisać, jest pomijane i zgłaszane w raporcie.
Wpis w raporcie: check_skipped
CHECK constraints that are DISABLE or ENABLE NOVALIDATE
nie jest tworzone
Oracle nie stosuje tych ograniczeń CHECK do już istniejących wierszy, więc wiersze mogą je łamać.
Wpis w raporcie: check_not_enforced
function-based, bitmap and domain indexes
nie jest tworzone
IntoSQL zapisuje indeksy b-tree na całych kolumnach; pozostałe utwórz ponownie po załadowaniu.
Wpis w raporcie: index_skipped
foreign keys
po danych z ENABLE NOVALIDATE, potem walidowany z ostrzeżeniem o osieroconych wierszach
Klucz od razu sprawdza nowe wiersze i jest walidowany na końcu; wiersze bez rodzica zostawiają go niezwalidowanym z ostrzeżeniem, zamiast zatrzymać ładowanie.
ON DELETE CASCADE that cascades in a cycle or along a second path
usunięte
Klucze obce w Oracle działają tylko przy usuwaniu, z CASCADE lub SET NULL.
Wpis w raporcie: foreign_key_action_unsupported
foreign keys to tables the export doesn't create, and DISABLE or NOVALIDATE ones
nie jest tworzone
Klucz nie może wskazywać tabeli, której nie ma, a klucz, którego Oracle nie sprawdza, może mieć wiersze bez rodzica.
Wpis w raporcie: foreign_key_skipped
names longer than Oracle 12.1 allows
skrócone
Od wersji 12.2 nazwy w Oracle mają do 128 bajtów; dłuższa nazwa jest skracana.
Wpis w raporcie: name_shortened
partitioned tables
jedna tabela z wierszami wszystkich partycji
Wiersze są te same; jeśli trzeba, podziel tabelę na partycje ponownie w Oracle.
Wpis w raporcie: partitions_dropped
several schemas in one export
jeden schemat, nazwa każdej tabeli zaczyna się od nazwy jej schematu
Skrypt ładuje się do schematu użytkownika, który go uruchamia, więc nazwy tabel z różnych schematów zaczynają się od nazwy schematu; eksport jednego schematu zachowuje nazwy swoich tabel.
Wpis w raporcie: schemas_merged
NOT NULL columns with values that become NULL
NOT NULL usunięte
Kolumna, której wartości musiały stać się NULL, nie może zachować NOT NULL, bo ładowanie by się zatrzymało.
Wpis w raporcie: not_null_relaxed
views, synonyms, types, packages, procedures, functions and other triggers
wymienione w raporcie
Ich kod jest napisany w PL/SQL, więc trafiają na listę do ręcznego odtworzenia.
Wpis w raporcie: not_converted_objects
exports without CREATE TABLE (data only)
typy odczytane z wartości
Eksport samych danych zawiera tylko wiersze, więc typy pochodzą z wartości.
Wpis w raporcie: no_schema
expressions in INSERT values other than the ones exports write
NULL
Konwerter, który nie uruchamia bazy danych, nie może ich obliczyć; to_date, to_timestamp, TO_CLOB, HEXTORAW i inne, które zapisują eksporty, są odczytywane.
Wpis w raporcie: expression_value
types IntoSQL doesn't know, and object types
CLOB
Tekst mieści każdą wartość; zmień typ po załadowaniu.
Wpis w raporcie: unknown_type
dates before year 1 and time zones given as region names
NULL
Wartość, która nie jest datą, staje się NULL, a raport ją liczy.
Wpis w raporcie: date_out_of_range
NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLE
NaN i Infinity zachowane
Typy zmiennoprzecinkowe w Oracle przechowują NaN i nieskończoność.
NUL characters in text
zachowane
VARCHAR2 i CLOB mogą zawierać znak NUL, więc wartość jest kopiowana bez zmian.
text that isn't valid in its encoding
błędne bajty jako znak zastępczy
Skrypt jest w UTF-8 i każda wartość musi być poprawnym tekstem.
Wpis w raporcie: invalid_utf8_replaced
text decoded twice (ñ)
skopiowane bez zmian
Skrypt zawiera dokładnie te znaki, więc są kopiowane; raport je wskazuje.
Wpis w raporcie: mojibake_suspected
| W pliku | W skrypcie | Wpis w raporcie |
|---|---|---|
| BOOLEAN (23ai) | BOOLEAN na 23ai, w przeciwnym razie NUMBER(1) z CHECK 0 i 1TRUE i FALSE pozostają true i false. | |
| VARCHAR2(n BYTE|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONG | te same typy, z długościami w BYTE lub CHARTe same typy tekstowe; LONG staje się CLOB, który preferuje każda wersja od 8. | |
| VARCHAR2 and NVARCHAR2 past what the target's own types hold | VARCHAR2(4000 CHAR), gdy każda wartość mieści się w 4000 bajtach, w przeciwnym razie CLOBVARCHAR2 mieści domyślnie 4000 bajtów, a Oracle nie indeksuje CLOB, więc tekst zostaje VARCHAR2, gdy jego wartości się mieszczą, a CLOB, gdy nie. | text_as_lob |
| NUMBER, NUMBER(p,s), FLOAT(b) | te same typy NUMBERTe same typy NUMBER i FLOAT, ze wszystkimi cyframi. | |
| INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECOND | te same typy INTERVALTe same interwały. | |
| DATE, TIMESTAMP(p) | DATE i TIMESTAMP(p), jak zadeklarowanoTe same typy, więc każda data zachowuje godzinę z dokładnością do sekundy. | |
| TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE | te same typyOracle przechowuje przesunięcia od -12:00 do +14:00; wartość z przesunięciem poza -12:00 jest zapisywana w UTC, ten sam moment. | |
| JSON (21c), and CLOB holding JSON | JSON od 21c, w przeciwnym razie CLOBTe same wartości JSON; SQL NULL zapisany przez eksport jako 'null' pozostaje NULL. | |
| BLOB, RAW(n), LONG RAW | te same typy; LONG RAW jako BLOBBajty pozostają bajtami. | |
| ROWID, UROWID, XMLTYPE, SDO_GEOMETRY | CLOB z ich tekstemXMLTYPE, ROWID i UROWID zachowują swój tekst w CLOB, więc skrypt ładuje się na każdej wersji od 19c. | type_replaced |
| collations that ignore case (BINARY_CI) | dokładne porównaniePorównywania kolumn nie są zapisywane, więc kolumna, która ignorowała wielkość liter (BINARY_CI), teraz odróżnia Ana od ana. | case_insensitive_collation |
| identity columns, and a sequence a BEFORE INSERT trigger assigns | GENERATED BY DEFAULT ON NULL AS IDENTITY, kontynuowane po najwyższym idSkopiowane id ładują się bez zmian, a licznik idzie dalej od najwyższego z nich. Kolumna, którą wyzwalacz wypełnia z sekwencji (sposób sprzed 12c), też staje się kolumną identity. | |
| identity columns the target can't count | zwykła liczba całkowitaOracle liczy jedną kolumnę identity na tabelę; każda inna zachowuje wartości bez licznika. | counter_dropped |
| CREATE SEQUENCE | CREATE SEQUENCE z tymi samymi opcjamiEksport zapisuje, dokąd doszła sekwencja, jako jej START WITH, więc kontynuuje ona od tego miejsca. | |
| virtual columns (GENERATED ALWAYS AS ... VIRTUAL) | kolumny wirtualneTe same kolumny wirtualne. | stored_as_virtual |
| virtual columns with functions IntoSQL doesn't write, and the || operator | zwykła kolumnaFormuła, której nie da się zapisać dla Oracle, zostawia zwykłą kolumnę i wpis w raporcie; wartości, które eksport zapisał dla kolumn wirtualnych, są pomijane, a Oracle nie może ich obliczyć. | generated_not_translated |
| defaults with functions IntoSQL doesn't write (SYS_GUID(), ||) | brak wartości domyślnejWartość domyślna, której nie da się zapisać, jest pomijana i zgłaszana w raporcie. | default_not_translated |
| CHECK constraints | przetłumaczoneTe same ograniczenia CHECK, sprawdzane przy ładowaniu każdego wiersza. | |
| CHECK constraints with functions IntoSQL doesn't write | nie jest tworzoneOgraniczenie CHECK, którego nie da się zapisać, jest pomijane i zgłaszane w raporcie. | check_skipped |
| CHECK constraints that are DISABLE or ENABLE NOVALIDATE | nie jest tworzoneOracle nie stosuje tych ograniczeń CHECK do już istniejących wierszy, więc wiersze mogą je łamać. | check_not_enforced |
| function-based, bitmap and domain indexes | nie jest tworzoneIntoSQL zapisuje indeksy b-tree na całych kolumnach; pozostałe utwórz ponownie po załadowaniu. | index_skipped |
| foreign keys | po danych z ENABLE NOVALIDATE, potem walidowany z ostrzeżeniem o osieroconych wierszachKlucz od razu sprawdza nowe wiersze i jest walidowany na końcu; wiersze bez rodzica zostawiają go niezwalidowanym z ostrzeżeniem, zamiast zatrzymać ładowanie. | |
| ON DELETE CASCADE that cascades in a cycle or along a second path | usunięteKlucze obce w Oracle działają tylko przy usuwaniu, z CASCADE lub SET NULL. | foreign_key_action_unsupported |
| foreign keys to tables the export doesn't create, and DISABLE or NOVALIDATE ones | nie jest tworzoneKlucz nie może wskazywać tabeli, której nie ma, a klucz, którego Oracle nie sprawdza, może mieć wiersze bez rodzica. | foreign_key_skipped |
| names longer than Oracle 12.1 allows | skróconeOd wersji 12.2 nazwy w Oracle mają do 128 bajtów; dłuższa nazwa jest skracana. | name_shortened |
| partitioned tables | jedna tabela z wierszami wszystkich partycjiWiersze są te same; jeśli trzeba, podziel tabelę na partycje ponownie w Oracle. | partitions_dropped |
| several schemas in one export | jeden schemat, nazwa każdej tabeli zaczyna się od nazwy jej schematuSkrypt ładuje się do schematu użytkownika, który go uruchamia, więc nazwy tabel z różnych schematów zaczynają się od nazwy schematu; eksport jednego schematu zachowuje nazwy swoich tabel. | schemas_merged |
| NOT NULL columns with values that become NULL | NOT NULL usunięteKolumna, której wartości musiały stać się NULL, nie może zachować NOT NULL, bo ładowanie by się zatrzymało. | not_null_relaxed |
| views, synonyms, types, packages, procedures, functions and other triggers | wymienione w raporcieIch kod jest napisany w PL/SQL, więc trafiają na listę do ręcznego odtworzenia. | not_converted_objects |
| exports without CREATE TABLE (data only) | typy odczytane z wartościEksport samych danych zawiera tylko wiersze, więc typy pochodzą z wartości. | no_schema |
| expressions in INSERT values other than the ones exports write | NULLKonwerter, który nie uruchamia bazy danych, nie może ich obliczyć; to_date, to_timestamp, TO_CLOB, HEXTORAW i inne, które zapisują eksporty, są odczytywane. | expression_value |
| types IntoSQL doesn't know, and object types | CLOBTekst mieści każdą wartość; zmień typ po załadowaniu. | unknown_type |
| dates before year 1 and time zones given as region names | NULLWartość, która nie jest datą, staje się NULL, a raport ją liczy. | date_out_of_range |
| NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLE | NaN i Infinity zachowaneTypy zmiennoprzecinkowe w Oracle przechowują NaN i nieskończoność. | |
| NUL characters in text | zachowaneVARCHAR2 i CLOB mogą zawierać znak NUL, więc wartość jest kopiowana bez zmian. | |
| text that isn't valid in its encoding | błędne bajty jako znak zastępczySkrypt jest w UTF-8 i każda wartość musi być poprawnym tekstem. | invalid_utf8_replaced |
| text decoded twice (ñ) | skopiowane bez zmianSkrypt zawiera dokładnie te znaki, więc są kopiowane; raport je wskazuje. | mojibake_suspected |
Załaduj skrypt do Oracle
Skrypt tworzy tabele, kopiuje wiersze, a potem dodaje klucze, indeksy i klucze obce, więc ładuje się szybko i zatrzymuje przy pierwszym błędzie.
NLS_LANG=.AL32UTF8 sqlplus -S -L user@//localhost/mydb @oracle.oracle.sqlKlucze obce są dodawane z ENABLE NOVALIDATE, więc nowe wiersze są sprawdzane od razu, a potem walidowane. Jeśli stary wiersz wskazuje na nieistniejący wiersz, skrypt podaje, którego ograniczenia to dotyczy, i zostawia je niezwalidowane, zamiast przerwać w połowie.
Przy dużym zrzucie uruchom SQL*Plus na tej samej maszynie co baza danych. Skrypt zatwierdza co 100 wierszy. Użytkownik, który go uruchamia, potrzebuje CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER i CREATE PROCEDURE oraz limitu w swojej przestrzeni tabel.
Jak zrobić zrzut Oracle dla najlepszego wyniku
Konwerter odczytuje to, co zawiera zrzut. Te opcje zachowują w nim więcej twoich danych:
- W SQL Developer wybierz Tools, Database Export, z DDL i formatem danych Insert. SQLcl zapisuje to samo z SET SQLFORMAT INSERT.
- Przed eksportem uruchom ALTER SESSION SET NLS_DATE_FORMAT = 'SYYYY-MM-DD HH24:MI:SS': domyślny format zapisuje daty bez godziny i stulecia.
- Plik .dmp z exp lub expdp jest binarny: zaimportuj go do bazy Oracle, np. Oracle Database Free w Dockerze, i wyeksportuj przez SQL Developer.
Co nie jest konwertowane
Widoki, wyzwalacze, procedury, funkcje i inne obiekty napisane we własnym języku Oracle są wymienione w raporcie z nazwy i nigdy nie są pomijane po cichu, więc możesz sprawdzić każdy z nich w wersji Oracle, do której ładujesz, zanim go odtworzysz.
Pytania o przenoszenie Oracle między wersjami
Nie ma tu odpowiedzi? Napisz do nas przez stronę kontaktu, a odpowie człowiek. Strona kontaktu
Czy mój zrzut jest wysyłany?
Nie. Konwerter działa w przeglądarce i odczytuje zrzut z dysku po kawałku, więc nigdy nie opuszcza on twojego komputera. Aplikacja na komputer i wiersz poleceń też konwertują na twoim komputerze.
Jak duży może być zrzut?
Konwerter nigdy nie trzyma całego zrzutu w pamięci: czyta plik dwa razy, fragmentami, i zapisuje skrypt na bieżąco. Zrzuty wielogigabajtowe konwertują się w przeglądarce, w aplikacji na komputer i w wierszu poleceń.
Czy mogę przekonwertować plik .dmp z exp lub expdp?
Nie bezpośrednio: Data Pump i oryginalny Export zapisują format binarny, który czyta tylko Oracle. Zaimportuj plik do dowolnej bazy Oracle (Oracle Database Free działa w Dockerze) i wyeksportuj go przez Database Export w SQL Developer lub przez SQLcl. Konwerter informuje o tym, gdy dostanie plik .dmp.
Z jakich wersji Oracle może pochodzić eksport?
Eksporty z SQL Developer i SQLcl, z definicjami tabel z DBMS_METADATA, z Oracle od wersji 11g. Każdy testowy eksport pochodzi z Oracle 21c i 23ai, w sesjach amerykańskich, niemieckich i ISO, i jest porównywany ze źródłem komórka po komórce.
Co dzieje się z NUMBER, DATE i innymi typami Oracle?
Pozostają bez zmian: NUMBER z precyzją, DATE, TIMESTAMP, interwały, CHAR i VARCHAR2 z długościami, RAW i LOB-y. XMLTYPE i JSON zachowują swój tekst w CLOB, więc skrypt ładuje się na 19c.
Czy kolumny identity i sekwencje są zachowywane?
Tak. Kolumny identity i sekwencje pozostają bez zmian i kontynuują od miejsca, do którego według eksportu doszły.
A pakiety PL/SQL, procedury i wyzwalacze?
Raport wymienia je z nazwy, ale nie są konwertowane, więc możesz je odtworzyć, gdy tabele będą już na miejscu.
Na jakich wersjach Oracle ładuje się skrypt?
Oracle 19c i nowsze. Każdy testowy eksport ładuje się na 21c i 23ai i zatrzymuje przy pierwszym błędzie, jeśli coś pójdzie nie tak.