Chuyển SQLite sang Oracle
Thả tệp cơ sở dữ liệu SQLite (.db, .sqlite, .sqlite3) hoặc đoạn SQL mà lệnh .dump của sqlite3 ghi ra, và tải xuống tập lệnh Oracle với cùng bảng, khóa, chỉ mục và dữ liệu. Mỗi cột nhận kiểu mà giá trị của nó vừa, và mọi giá trị Oracle không chứa được nguyên trạng đều được liệt kê trong báo cáo.
Đã chuyển đổi 18 hàng, không có bản sửa, không hàng nào bị từ chối
Các bảng trong shop_2024_sqlite.sqlBản dump SQLite · do sqlite3 ghi · utf-8
customersghi thành CUSTOMERS8 hàng
7 cột 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 ordersghi thành ORDERS10 hàng
9 cột 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
Không được chuyển đổi
- Khung nhìn order_totals
- Trình kích hoạt orders_shipped
Mỗi cơ sở dữ liệu viết các đối tượng này bằng ngôn ngữ riêng. Hãy viết lại chúng cho 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;
Bản sửa
Không có gì cần sửa.
Cần xem lại
- 1 cột văn bản trong nguồn so sánh không phân biệt hoa thường; Oracle so sánh chính xác, nên khóa duy nhất và tìm kiếm có thể hoạt động khác. Hãy dùng một collation hoặc kiểu cột không phân biệt hoa thường cho các cột cần điều đó.
- 2 khung nhìn, trình kích hoạt, thủ tục hoặc sự kiện không được chuyển đổi; báo cáo liệt kê từng mục. Hãy tạo lại chúng thủ công trong Oracle.
Tệp được chuyển đổi ngay trên máy tính này và không bao giờ được tải lên.
Mẫu khác:
Những gì thay đổi từ SQLite sang Oracle
Mỗi hàng là một quy tắc trình chuyển đổi áp dụng, kèm dòng báo cáo được ghi khi quy tắc thay đổi dữ liệu của bạn.
declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none)
kiểu mà mọi giá trị trong cột đều vừa
SQLite giữ mọi giá trị trong mọi cột, nên kiểu đã khai báo chỉ là gợi ý: mỗi cột nhận kiểu mà mọi giá trị của nó đều vừa, và cột chứa giá trị hỗn hợp giữ văn bản của chúng.
BOOLEAN, BOOL
NUMBER(1) kèm CHECK 0 và 1
Khi mọi giá trị là 0 hoặc 1; cột còn chứa giá trị khác thì giữ chúng dưới dạng số hoặc văn bản.
TEXT, VARCHAR(n), CHAR(n), CLOB
VARCHAR2(n CHAR) khi mọi giá trị vừa, nếu không thì CLOB
SQLite không bao giờ áp đặt độ dài; độ dài đã khai báo chỉ được giữ khi mọi giá trị đều vừa.
TEXT and VARCHAR(n) longer than 4000 bytes
VARCHAR2(4000 CHAR) khi mọi giá trị vừa 4000 byte (750 ký tự trong khóa), nếu không thì CLOB
VARCHAR2 mặc định chứa 4000 byte và Oracle không lập chỉ mục được CLOB, nên văn bản giữ VARCHAR2 khi giá trị vừa và là CLOB khi không vừa.
Dòng báo cáo: text_as_lob
DECIMAL(p,s), NUMERIC
kiểu chính xác khi mọi giá trị đều vừa, nếu không thì double
SQLite lưu chúng dưới dạng số nguyên hoặc double; độ chính xác đã khai báo chỉ được giữ khi các giá trị vừa.
BLOB, and columns holding bytes
BLOB
Byte vẫn là byte; văn bản và số trong cùng cột được giữ dưới dạng byte của chúng.
DATE, DATETIME, TIMESTAMP holding ISO 8601 text
DATE hoặc TIMESTAMP(p), tùy giá trị chứa gì
Khi mọi giá trị là ngày hoặc ngày và giờ; số epoch và văn bản khác giữ nguyên giá trị.
JSON holding JSON text
CLOB
Khi mọi giá trị là đối tượng hoặc mảng JSON.
Infinity in REAL columns
giữ thành BINARY_DOUBLE_INFINITY
Double của Oracle chứa được vô cực.
INTEGER PRIMARY KEY, AUTOINCREMENT
GENERATED BY DEFAULT ON NULL AS IDENTITY, tiếp tục sau id lớn nhất hoặc giá trị của sqlite_sequence
Chỉ cột được khai báo đúng là INTEGER PRIMARY KEY mới là rowid; mỗi hàng giữ id của nó, và bộ đếm bắt đầu sau id lớn nhất từng được cấp.
COLLATE NOCASE
so sánh chính xác
Oracle so sánh văn bản chính xác trừ khi được chỉ định khác; cột NOCASE mất khả năng không phân biệt hoa thường.
Dòng báo cáo: case_insensitive_collation
generated columns
cột ảo
Oracle chỉ tính cột tính toán khi đọc; cột STORED thành cột ảo với cùng giá trị.
Dòng báo cáo: stored_as_virtual
generated columns with functions IntoSQL doesn't write, and the || operator
một cột thường
Công thức không viết được để lại một cột thường và một dòng trong báo cáo; bản dump không có giá trị cho cột tính toán.
Dòng báo cáo: generated_not_translated
defaults with functions IntoSQL doesn't write (strftime, randomblob)
không có giá trị mặc định
Giá trị mặc định không viết được sẽ bị bỏ và được báo cáo; CURRENT_TIMESTAMP và datetime('now') vẫn được viết.
Dòng báo cáo: default_not_translated
CHECK constraints
được chuyển đổi
Cùng các ràng buộc kiểm tra, được kiểm tra khi từng hàng được nạp.
CHECK constraints with functions IntoSQL doesn't write
không được tạo
Ràng buộc kiểm tra không viết được sẽ bị bỏ và được báo cáo.
Dòng báo cáo: check_skipped
partial and expression indexes
không được tạo
IntoSQL ghi chỉ mục trên toàn bộ cột; hãy tạo lại các chỉ mục khác sau khi nạp.
Dòng báo cáo: index_skipped
foreign keys (unenforced unless PRAGMA foreign_keys=ON)
sau dữ liệu ENABLE NOVALIDATE, rồi xác thực
SQLite chỉ kiểm tra khóa ngoại khi được yêu cầu, nên hàng không có hàng cha khá phổ biến: chúng vẫn được nạp, và khóa ở trạng thái chưa kiểm tra kèm cảnh báo thay vì dừng quá trình nạp.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT
bị bỏ
Khóa ngoại của Oracle chỉ tác động khi xóa, với CASCADE hoặc SET NULL.
Dòng báo cáo: foreign_key_action_unsupported
empty strings and empty blobs
NULL
Oracle lưu chuỗi rỗng là NULL, nên giá trị từng là ' được đọc lại là NULL. Báo cáo đếm chúng theo từng cột.
Dòng báo cáo: empty_string_null
foreign keys to tables the dump doesn't create
không được tạo
Khóa không thể tham chiếu tới bảng không tồn tại.
Dòng báo cáo: foreign_key_skipped
primary keys holding NULL, and NOT NULL columns with values that become NULL
bỏ NOT NULL
SQLite cho phép khóa chính không phải rowid chứa NULL; cột không thể là NOT NULL ở đích, nếu không quá trình nạp sẽ dừng.
Dòng báo cáo: not_null_relaxed
views, triggers and virtual tables (FTS, R*Tree)
được liệt kê trong báo cáo
Mã của chúng viết bằng ngôn ngữ riêng của SQLite, và bảng ảo cần các mô-đun của SQLite; chúng được liệt kê để bạn tạo lại. Các bảng nội bộ của chúng không được sao chép.
Dòng báo cáo: not_converted_objects
dumps without CREATE TABLE (--data-only)
kiểu suy ra từ giá trị
Bản dump chỉ có dữ liệu thì chỉ có các hàng, nên kiểu được suy ra từ giá trị và các cột được đánh số.
Dòng báo cáo: no_schema
expressions in INSERT values other than the text functions dumps write
NULL
unistr(), replace(), char() và || được tính như cách shell ghi chúng; các biểu thức khác không tính được nếu không có cơ sở dữ liệu.
Dòng báo cáo: expression_value
NUL characters in text
được giữ
Shell sqlite3 và Python cắt văn bản tại ký tự NUL khi dump, nên chỉ phần đứng trước nó có trong bản dump.
text that isn't valid UTF-8
byte lỗi thành ký tự thay thế
Bản dump ghi văn bản như vậy dưới dạng byte thô; tập lệnh là UTF-8.
Dòng báo cáo: invalid_utf8_replaced
text decoded twice (ñ)
sao chép nguyên trạng
Bản dump chứa đúng các ký tự này, nên chúng được sao chép; báo cáo chỉ ra chúng.
Dòng báo cáo: mojibake_suspected
| Trong SQLite | Trong Oracle | Dòng báo cáo |
|---|---|---|
| declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none) | kiểu mà mọi giá trị trong cột đều vừaSQLite giữ mọi giá trị trong mọi cột, nên kiểu đã khai báo chỉ là gợi ý: mỗi cột nhận kiểu mà mọi giá trị của nó đều vừa, và cột chứa giá trị hỗn hợp giữ văn bản của chúng. | |
| BOOLEAN, BOOL | NUMBER(1) kèm CHECK 0 và 1Khi mọi giá trị là 0 hoặc 1; cột còn chứa giá trị khác thì giữ chúng dưới dạng số hoặc văn bản. | |
| TEXT, VARCHAR(n), CHAR(n), CLOB | VARCHAR2(n CHAR) khi mọi giá trị vừa, nếu không thì CLOBSQLite không bao giờ áp đặt độ dài; độ dài đã khai báo chỉ được giữ khi mọi giá trị đều vừa. | |
| TEXT and VARCHAR(n) longer than 4000 bytes | VARCHAR2(4000 CHAR) khi mọi giá trị vừa 4000 byte (750 ký tự trong khóa), nếu không thì CLOBVARCHAR2 mặc định chứa 4000 byte và Oracle không lập chỉ mục được CLOB, nên văn bản giữ VARCHAR2 khi giá trị vừa và là CLOB khi không vừa. | text_as_lob |
| DECIMAL(p,s), NUMERIC | kiểu chính xác khi mọi giá trị đều vừa, nếu không thì doubleSQLite lưu chúng dưới dạng số nguyên hoặc double; độ chính xác đã khai báo chỉ được giữ khi các giá trị vừa. | |
| BLOB, and columns holding bytes | BLOBByte vẫn là byte; văn bản và số trong cùng cột được giữ dưới dạng byte của chúng. | |
| DATE, DATETIME, TIMESTAMP holding ISO 8601 text | DATE hoặc TIMESTAMP(p), tùy giá trị chứa gìKhi mọi giá trị là ngày hoặc ngày và giờ; số epoch và văn bản khác giữ nguyên giá trị. | |
| JSON holding JSON text | CLOBKhi mọi giá trị là đối tượng hoặc mảng JSON. | |
| Infinity in REAL columns | giữ thành BINARY_DOUBLE_INFINITYDouble của Oracle chứa được vô cực. | |
| INTEGER PRIMARY KEY, AUTOINCREMENT | GENERATED BY DEFAULT ON NULL AS IDENTITY, tiếp tục sau id lớn nhất hoặc giá trị của sqlite_sequenceChỉ cột được khai báo đúng là INTEGER PRIMARY KEY mới là rowid; mỗi hàng giữ id của nó, và bộ đếm bắt đầu sau id lớn nhất từng được cấp. | |
| COLLATE NOCASE | so sánh chính xácOracle so sánh văn bản chính xác trừ khi được chỉ định khác; cột NOCASE mất khả năng không phân biệt hoa thường. | case_insensitive_collation |
| generated columns | cột ảoOracle chỉ tính cột tính toán khi đọc; cột STORED thành cột ảo với cùng giá trị. | stored_as_virtual |
| generated columns with functions IntoSQL doesn't write, and the || operator | một cột thườngCông thức không viết được để lại một cột thường và một dòng trong báo cáo; bản dump không có giá trị cho cột tính toán. | generated_not_translated |
| defaults with functions IntoSQL doesn't write (strftime, randomblob) | không có giá trị mặc địnhGiá trị mặc định không viết được sẽ bị bỏ và được báo cáo; CURRENT_TIMESTAMP và datetime('now') vẫn được viết. | default_not_translated |
| CHECK constraints | được chuyển đổiCùng các ràng buộc kiểm tra, được kiểm tra khi từng hàng được nạp. | |
| CHECK constraints with functions IntoSQL doesn't write | không được tạoRàng buộc kiểm tra không viết được sẽ bị bỏ và được báo cáo. | check_skipped |
| partial and expression indexes | không được tạoIntoSQL ghi chỉ mục trên toàn bộ cột; hãy tạo lại các chỉ mục khác sau khi nạp. | index_skipped |
| foreign keys (unenforced unless PRAGMA foreign_keys=ON) | sau dữ liệu ENABLE NOVALIDATE, rồi xác thựcSQLite chỉ kiểm tra khóa ngoại khi được yêu cầu, nên hàng không có hàng cha khá phổ biến: chúng vẫn được nạp, và khóa ở trạng thái chưa kiểm tra kèm cảnh báo thay vì dừng quá trình nạp. | |
| ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT | bị bỏKhóa ngoại của Oracle chỉ tác động khi xóa, với CASCADE hoặc SET NULL. | foreign_key_action_unsupported |
| empty strings and empty blobs | NULLOracle lưu chuỗi rỗng là NULL, nên giá trị từng là ' được đọc lại là NULL. Báo cáo đếm chúng theo từng cột. | empty_string_null |
| foreign keys to tables the dump doesn't create | không được tạoKhóa không thể tham chiếu tới bảng không tồn tại. | foreign_key_skipped |
| primary keys holding NULL, and NOT NULL columns with values that become NULL | bỏ NOT NULLSQLite cho phép khóa chính không phải rowid chứa NULL; cột không thể là NOT NULL ở đích, nếu không quá trình nạp sẽ dừng. | not_null_relaxed |
| views, triggers and virtual tables (FTS, R*Tree) | được liệt kê trong báo cáoMã của chúng viết bằng ngôn ngữ riêng của SQLite, và bảng ảo cần các mô-đun của SQLite; chúng được liệt kê để bạn tạo lại. Các bảng nội bộ của chúng không được sao chép. | not_converted_objects |
| dumps without CREATE TABLE (--data-only) | kiểu suy ra từ giá trịBản dump chỉ có dữ liệu thì chỉ có các hàng, nên kiểu được suy ra từ giá trị và các cột được đánh số. | no_schema |
| expressions in INSERT values other than the text functions dumps write | NULLunistr(), replace(), char() và || được tính như cách shell ghi chúng; các biểu thức khác không tính được nếu không có cơ sở dữ liệu. | expression_value |
| NUL characters in text | được giữShell sqlite3 và Python cắt văn bản tại ký tự NUL khi dump, nên chỉ phần đứng trước nó có trong bản dump. | |
| text that isn't valid UTF-8 | byte lỗi thành ký tự thay thếBản dump ghi văn bản như vậy dưới dạng byte thô; tập lệnh là UTF-8. | invalid_utf8_replaced |
| text decoded twice (ñ) | sao chép nguyên trạngBản dump chứa đúng các ký tự này, nên chúng được sao chép; báo cáo chỉ ra chúng. | mojibake_suspected |
Nạp tập lệnh vào Oracle
Tập lệnh tạo bảng, sao chép các hàng, rồi thêm khóa, chỉ mục và khóa ngoại, nên nạp nhanh và dừng ở lỗi đầu tiên.
NLS_LANG=.AL32UTF8 sqlplus -S -L user@//localhost/mydb @sqlite.oracle.sqlKhóa ngoại được thêm với ENABLE NOVALIDATE, nên hàng mới được kiểm tra ngay, rồi được xác thực. Nếu một hàng cũ trỏ tới hàng không tồn tại, tập lệnh cho biết ràng buộc nào và để nó ở trạng thái chưa xác thực, thay vì thất bại giữa chừng.
Với bản dump lớn, hãy chạy SQL*Plus trên cùng máy với cơ sở dữ liệu. Tập lệnh commit sau mỗi 100 hàng. Người dùng chạy tập lệnh cần quyền CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER và CREATE PROCEDURE, cùng hạn mức trên tablespace của mình.
Tạo bản dump SQLite để có kết quả tốt nhất
Trình chuyển đổi đọc những gì bản dump chứa. Các tùy chọn sau giữ lại nhiều dữ liệu hơn trong đó:
- Chính tệp cơ sở dữ liệu được chuyển đổi nguyên trạng, đọc từng trang trong trình duyệt của bạn. Hãy đóng ứng dụng đang ghi vào tệp trước, để không thay đổi nào bị bỏ lại trong tệp -wal của nó.
- sqlite3 app.db .dump > app.sql ghi cùng cơ sở dữ liệu đó dưới dạng SQL, cũng chuyển đổi được, dạng .sql hoặc .sql.gz.
- DB Browser for SQLite ghi đoạn SQL đó qua File, Export, Database to SQL file, và iterdump() của Python cũng vậy.
Những gì không được chuyển đổi
Khung nhìn và trình kích hoạt được viết bằng ngôn ngữ riêng của SQLite. Chúng được liệt kê theo tên trong báo cáo, không bao giờ bị bỏ âm thầm, để bạn viết lại cho Oracle. Bảng ảo, như FTS5 và R*Tree, cũng được liệt kê, còn các bảng bóng của chúng bị bỏ qua.
Câu hỏi về SQLite sang Oracle
Chưa có câu trả lời ở đây? Hãy viết cho chúng tôi từ trang liên hệ, sẽ có người trả lời. Trang liên hệ
Bản dump của tôi có bị tải lên không?
Không. Trình chuyển đổi chạy trong trình duyệt và đọc bản dump từ ổ đĩa theo từng phần, nên nó không bao giờ rời khỏi máy tính của bạn. Ứng dụng máy tính và dòng lệnh cũng chuyển đổi ngay trên máy tính của bạn.
Bản dump có thể lớn đến đâu?
Trình chuyển đổi không bao giờ giữ toàn bộ bản dump trong bộ nhớ: nó đọc tệp hai lần, theo từng đoạn, và ghi tập lệnh trong lúc đọc. Bản dump nhiều gigabyte vẫn chuyển đổi được trong trình duyệt, trong ứng dụng máy tính và bằng dòng lệnh.
Tôi có thể chuyển đổi trực tiếp tệp .db không?
Có. Thả tệp .db, .sqlite hoặc .sqlite3: tệp được đọc trong trình duyệt của bạn và không bao giờ được tải lên. Văn bản có ký tự NUL và mọi chữ số của một giá trị double đều đến đúng như đã lưu, điều mà .dump có thể cắt bớt.
Bản dump có thể đến từ những phiên bản SQLite nào?
Tệp cơ sở dữ liệu từ SQLite 3.0 trở lên, dạng UTF-8 hoặc UTF-16, và bản dump từ lệnh .dump của shell sqlite3 hoặc iterdump() của Python. Mọi tệp và bản dump thử nghiệm đến từ sqlite3 3.31 đến 3.54, gồm cả bảng STRICT và WITHOUT ROWID, và được so với nguồn từng ô một.
Kiểu cột được quyết định thế nào khi SQLite không áp đặt chúng?
Kiểu đã khai báo chỉ là gợi ý và giá trị mới quyết định: cột trở thành NUMBER, BINARY_DOUBLE, DATE, TIMESTAMP, BLOB, VARCHAR2 hoặc CLOB khi mọi giá trị đều vừa. Chuỗi rỗng thành NULL, như cách Oracle lưu chúng, và báo cáo đếm chúng.
INTEGER PRIMARY KEY và AUTOINCREMENT có được giữ không?
Có. INTEGER PRIMARY KEY trở thành cột identity, mỗi hàng giữ id của nó, và id tiếp theo tiếp tục sau id lớn nhất, hoặc sau giá trị của sqlite_sequence khi có AUTOINCREMENT.
Còn khung nhìn và trình kích hoạt thì sao?
Chúng được liệt kê theo tên trong báo cáo và không được chuyển đổi, vì mỗi cơ sở dữ liệu viết chúng bằng ngôn ngữ riêng.
Tập lệnh nạp được trên những phiên bản Oracle nào?
Oracle 19c trở lên. Mọi bản dump thử nghiệm đều nạp được trên 21c và 23ai, và dừng ở lỗi đầu tiên nếu có sự cố.