Chuyển đến nội dung
Trang chủ IntoSQL

Chuyển SQL Server sang Oracle

Thả tập lệnh mà Generate Scripts của SSMS ghi với schema và dữ liệu, dạng .sql hoặc .sql.gz, UTF-16 hoặc UTF-8, 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 giá trị Oracle không chứa được nguyên trạng, và mọi đối tượng nó không hỗ trợ, đều được liệt kê trong báo cáo.

Tệp của bạn
sqlshop_2024_sqlserver.sqlTệp mẫu, 11 kB
Cơ sở dữ liệu của bạn

Đã chuyển đổi 18 hàng, 2 bản sửa, không hàng nào bị từ chối

Hiển thị

Các bảng trong shop_2024_sqlserver.sqlBản dump SQL Server · do SQL Server Management Objects ghi · utf-8

  • ordersghi thành ORDERS10 hàng1
    11 cột
    IDNUMBER(10) not null
    CUSTOMER_IDNUMBER(10) not null
    STATUSVARCHAR2(10 CHAR) not null
    TOTALNUMBER(19,4) not null
    ITEMSNUMBER(3) not null
    ORDERED_ATTIMESTAMP(0) not null
    SHIPPED_ATTIMESTAMP(7)
    NOTECLOB
    DETAILSCLOB
    ORDER_REFVARCHAR2(36 CHAR) not null
    TOTAL_WITH_TAXNUMBER(12,2)
  • customersghi thành CUSTOMERS8 hàng1
    8 cột
    IDNUMBER(10) not null
    NAMEVARCHAR2(100 CHAR) not null
    EMAILVARCHAR2(200 CHAR) not null
    COUNTRYVARCHAR2(2 CHAR) not null
    IS_ACTIVENUMBER(1) not null
    SIGNED_UPDATE
    CREATED_ATTIMESTAMP(0) WITH TIME ZONE not null
    ROW_VERSIONRAW(8)

Không được chuyển đổi

  • Khung nhìn paid_orders
  • Trình kích hoạt orders_no_negative

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 SQL Server 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 "ORDERS" (
    "ID" NUMBER(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1),
    "CUSTOMER_ID" NUMBER(10) NOT NULL,
    "STATUS" VARCHAR2(10 CHAR) DEFAULT 'pending' NOT NULL,
    "TOTAL" NUMBER(19,4) NOT NULL,
    "ITEMS" NUMBER(3) DEFAULT 1 NOT NULL,
    "ORDERED_AT" TIMESTAMP(0) NOT NULL,
    "SHIPPED_AT" TIMESTAMP(7),
    "NOTE" CLOB,
    "DETAILS" CLOB,
    "ORDER_REF" VARCHAR2(36 CHAR) NOT NULL,
    "TOTAL_WITH_TAX" NUMBER(12,2) GENERATED ALWAYS AS (CAST(CAST("TOTAL" * (1.16) AS NUMBER(12,2)) AS NUMBER(12,2))) VIRTUAL,
    CONSTRAINT "CK_ORDERS_ITEMS" CHECK ("ITEMS" >= 0),
    CONSTRAINT "CHECK2" CHECK ("STATUS" = 'cancelled' OR "STATUS" = 'shipped' OR "STATUS" = 'paid' OR "STATUS" = 'pending'),
    CONSTRAINT "CHECK3" CHECK ("TOTAL" >= (0))
);

CREATE TABLE "CUSTOMERS" (
    "ID" NUMBER(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1),
    "NAME" VARCHAR2(100 CHAR) NOT NULL,
    "EMAIL" VARCHAR2(200 CHAR) NOT NULL,
    "COUNTRY" VARCHAR2(2 CHAR) DEFAULT 'US' NOT NULL,
    "IS_ACTIVE" NUMBER(1) DEFAULT 1 NOT NULL,
    "SIGNED_UP" DATE,
    "CREATED_AT" TIMESTAMP(0) WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
    "ROW_VERSION" RAW(8),
    CONSTRAINT "CK_CUSTOMERS_IS_ACTIVE" CHECK ("IS_ACTIVE" IN (0, 1))
);

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 04:24:00.0000000 -06: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 09:11:42.0000000 +01:00'
);
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 20:05:17.0000000 +01:00'
);
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 10:40:00.0000000 +08: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 15:00:00.0000000 +01: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 10:30:00.0000000 +01: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-03-01 05:29:59.0000000 +05:30'
);
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 14:12:12.0000000 +02:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
1,
1,
'shipped',
129.9000,
3,
TIMESTAMP '2024-03-01 10:00:00.0000000',
TIMESTAMP '2024-03-02 16:30:00.1234567',
NULL,
'{"gift": false}',
'0b7a4c2e-3f1d-4e8a-9c55-1a2b3c4d5e6f'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
2,
2,
'paid',
54.0000,
1,
TIMESTAMP '2024-03-02 11:15:00.0000000',
NULL,
'Gift wrap 🎁',
'{"gift": true, "wrap": "red"}',
'1c8b5d3f-4a2e-4f9b-8d66-2b3c4d5e6f70'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
3,
1,
'cancelled',
12.5000,
1,
TIMESTAMP '2024-03-03 09:45:00.0000000',
NULL,
'Customer changed their mind',
NULL,
'2d9c6e4a-5b3f-4a0c-9e77-3c4d5e6f7081'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
4,
4,
'shipped',
980.0000,
12,
TIMESTAMP '2024-03-05 02:10:00.0000000',
TIMESTAMP '2024-03-07 08:00:00.0000000',
'请小心轻放',
'{"fragile": true}',
'3e0d7f5b-6c4a-4b1d-8f88-4d5e6f708192'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
5,
5,
'pending',
45.7500,
2,
TIMESTAMP '2024-03-08 17:20:00.0000000',
NULL,
'Leave at the door; ring twice',
NULL,
'4f1e806c-7d5b-4c2e-9a99-5e6f708192a3'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
6,
6,
'shipped',
310.4000,
5,
TIMESTAMP '2024-03-10 13:00:00.0000000',
TIMESTAMP '2024-03-11 09:00:00.0000000',
'Fragile: "glass"',
'{"fragile": true}',
'50f2917d-8e6c-4d3f-8baa-6f708192a3b4'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
7,
8,
'paid',
76.2000,
2,
TIMESTAMP '2024-03-11 18:45:00.0000000',
NULL,
NULL,
NULL,
'6103a28e-9f7d-4e40-9cbb-708192a3b4c5'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
8,
2,
'shipped',
19.9900,
1,
TIMESTAMP '2024-03-12 08:00:00.0000000',
TIMESTAMP '9999-12-31 23:59:59.9999999',
'Shipped date set to the maximum by an old import',
NULL,
'7214b39f-a08e-4f51-8dcc-8192a3b4c5d6'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
9,
3,
'shipped',
64.0000,
2,
TIMESTAMP '2024-03-14 15:30:00.0000000',
TIMESTAMP '2024-03-15 10:00:00.0000000',
'Two parcels',
'{"parcels": [1, 2]}',
'8325c4a0-b19f-4062-9edd-92a3b4c5d6e7'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
10,
7,
'paid',
1499.0000,
1,
TIMESTAMP '2024-03-15 21:05:00.0000000',
NULL,
'C:\Users\ravi\invoice.pdf',
NULL,
'9436d5b1-c2a0-4173-8fee-a3b4c5d6e7f8'
);
COMMIT;
END;
/

-- Keys, indexes, foreign keys, counters and triggers, after the rows.
ALTER TABLE "ORDERS" ADD CONSTRAINT "PK_ORDERS" PRIMARY KEY ("ID");
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "PK_CUSTOMERS" PRIMARY KEY ("ID");
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "UQ_CUSTOMERS_EMAIL" UNIQUE ("EMAIL");
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") 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 "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;
/
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';
DROP FUNCTION "INTOSQL_CLOB";
DROP FUNCTION "INTOSQL_BLOB";
COMMIT;
EXIT;

Bản sửa

  1. "total_with_tax" của orders được lưu trong nguồn; Oracle tính nó khi đọc.
  2. "row_version" của customers là phiên bản hàng do SQL Server tự đặt; bản dump không có giá trị cho nó, nên nó là RAW(8) và để trống.

Cần xem lại

  • 6 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.
  • Ràng buộc kiểm tra check1 trên orders không viết được cho Oracle (function isjson), nên không được tạo. Hãy viết ràng buộc kiểm tra thủ công nếu nó quan trọng.
  • Chỉ mục idx_orders_pending trên orders dùng một biểu thức không viết được cho Oracle (filtered index), nên không được tạo. Hãy tạo chỉ mục thủ công nếu truy vấn cần nó.
  • Giá trị mặc định của "order_ref" trong orders không viết được cho Oracle (function uuid), nên cột không có giá trị mặc định. Hãy thêm giá trị mặc định thủ công nếu hàng mới cần nó.

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ừ SQL Server 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.

  • bit

    NUMBER(1) kèm CHECK 0 và 1

    Oracle 21c không có kiểu cột boolean; 1 và 0 giữ được giá trị trên mọi phiên bản.

  • char(n), varchar(n), nchar(n), nvarchar(n)

    VARCHAR2(n CHAR), đếm theo ký tự

    Độ dài đếm theo ký tự, như nvarchar của SQL Server.

  • varchar(max), nvarchar(max), text, ntext

    VARCHAR2(4000 CHAR) khi mọi giá trị vừa 4000 byte, 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

  • empty strings and empty binary values

    NULL

    Oracle lưu chuỗi rỗng dưới dạng NULL, nên giá trị từng là ' sẽ đượ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

  • decimal(p,s), money, smallmoney

    NUMBER(p,s); money thành NUMBER(19,4)

    NUMBER chứa 38 chữ số, như decimal, nên mọi giá trị đều chính xác.

  • datetime, datetime2, smalldatetime

    TIMESTAMP(p)

    datetime là thời gian theo đồng hồ, giống TIMESTAMP của Oracle, vốn giữ đến chín chữ số của giây. date thành DATE, kiểu cũng chứa giờ trong ngày, luôn ở nửa đêm.

  • datetimeoffset

    TIMESTAMP WITH TIME ZONE, với độ lệch của từng giá trị

    Oracle giữ độ lệch từ -12:00 đến +14:00; giá trị có độ lệch vượt quá -12:00 được ghi theo UTC, cùng một thời điểm.

  • time

    INTERVAL DAY TO SECOND tính từ nửa đêm

    Oracle không có kiểu giờ trong ngày; một khoảng thời gian tính từ nửa đêm chứa được mọi giá trị.

  • dates that aren't valid

    NULL

    Giá trị không phải ngày sẽ thành NULL và báo cáo đếm nó.

    Dòng báo cáo: date_out_of_range

  • json (SQL Server 2025)

    CLOB

    Cùng các giá trị JSON, mà hàm JSON của Oracle đọc được.

  • uniqueidentifier

    VARCHAR2(36)

    Cùng các định danh, viết bằng chữ thường.

  • binary, varbinary, image

    RAW(n) và BLOB

    Byte vẫn là byte.

  • geometry, geography

    BLOB với byte riêng của SQL Server

    SSMS ghi giá trị không gian theo định dạng tuần tự hóa riêng của SQL Server, được giữ nguyên từng byte.

    Dòng báo cáo: spatial_as_native

  • rowversion, timestamp

    BLOB, để trống

    SQL Server tự đặt phiên bản hàng và SSMS không ghi giá trị cho nó.

    Dòng báo cáo: rowversion_empty

  • xml, sql_variant, hierarchyid, vector

    VARCHAR2 hoặc CLOB với văn bản của từng giá trị

    Oracle không có kiểu tương đương; xml và sql_variant giữ văn bản của từng giá trị và hierarchyid giữ đường dẫn của nó, ví dụ /1/2/.

    Dòng báo cáo: type_replaced

  • collations that ignore case (_CI_)

    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, nên cột từng không phân biệt hoa thường trong SQL Server giờ phân biệt Ana và ana.

    Dòng báo cáo: case_insensitive_collation

  • IDENTITY

    GENERATED BY DEFAULT ON NULL AS IDENTITY, tiếp tục sau id lớn nhất

    Các id đã sao chép được nạp nguyên trạng, và bộ đếm tiếp tục sau id lớn nhất.

  • CREATE SEQUENCE

    CREATE SEQUENCE với cùng các tùy chọn

    Sequence của Oracle hoạt động giống vậy. SSMS không ghi sequence đã chạy đến đâu, nên nó bắt đầu từ điểm lúc được tạo.

  • computed columns

    cột ảo

    Oracle chỉ tính cột tính toán khi đọc; cột PERSISTED thành cột ảo với cùng giá trị.

    Dòng báo cáo: stored_as_virtual

  • computed columns with functions Oracle lacks

    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; SSMS không ghi giá trị cho cột tính toán.

    Dòng báo cáo: generated_not_translated

  • defaults with functions Oracle lacks, and NEXT VALUE FOR

    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.

    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 Oracle lacks

    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

  • CHECK constraints added WITH NOCHECK or disabled

    không được tạo

    SQL Server không áp dụng các ràng buộc kiểm tra này, nên các hàng có thể vi phạm chúng.

    Dòng báo cáo: check_not_enforced

  • filtered and columnstore indexes, and indexes on CLOB columns

    không được tạo

    IntoSQL ghi chỉ mục b-tree 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

    sau dữ liệu với ENABLE NOVALIDATE, rồi xác thực kèm cảnh báo về hàng mồ côi

    Khóa kiểm tra hàng mới ngay và được xác thực sau cùng; hàng không có hàng cha khiến khóa ở trạng thái chưa xác thực 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ỉ hành động khi xóa, với CASCADE hoặc SET NULL.

    Dòng báo cáo: foreign_key_action_unsupported

  • names over 128 bytes

    rút ngắn

    Tên trong Oracle 12.2 trở lên chứa 128 byte; tên trong SQL Server chứa 128 ký tự.

    Dòng báo cáo: name_shortened

  • 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

  • tables on a partition scheme

    một bảng chứa các hàng của mọi phân vùng

    Các hàng giữ nguyên; hãy phân vùng lại bảng trong Oracle nếu cần.

    Dòng báo cáo: partitions_dropped

  • temporal tables (SYSTEM_VERSIONING)

    hai bảng: các hàng hiện tại và lịch sử

    Bảng và bảng lịch sử của nó được sao chép thành bảng thường; Oracle không tự giữ lịch sử.

    Dòng báo cáo: system_versioning_dropped

  • schemas

    một schema, mỗi bảng có tên schema ở đầu

    Tập lệnh nạp vào schema của người dùng chạy nó, nên bảng của các schema khác nhau có tên schema ở đầu; bảng trong dbo giữ nguyên tên.

    Dòng báo cáo: schemas_merged

  • NOT NULL columns with values that become NULL

    bỏ NOT NULL

    Cột có giá trị phải chuyển thành NULL không thể giữ NOT NULL, nếu không quá trình nạp sẽ dừng.

    Dòng báo cáo: not_null_relaxed

  • views, functions, procedures, triggers, synonyms, types and partition functions

    được liệt kê trong báo cáo

    Mã của chúng viết bằng T-SQL, nên được liệt kê để bạn tạo lại.

    Dòng báo cáo: not_converted_objects

  • scripts without CREATE TABLE (data only)

    kiểu suy ra từ giá trị

    Tập lệnh chỉ có dữ liệu thì chỉ có các hàng, nên kiểu được suy ra từ giá trị.

    Dòng báo cáo: no_schema

  • expressions in INSERT values

    NULL

    Trình chuyển đổi không chạy cơ sở dữ liệu thì không tính được chúng.

    Dòng báo cáo: expression_value

  • types IntoSQL doesn't know

    CLOB

    Văn bản chứa được mọi giá trị; hãy đổi kiểu sau khi nạp.

    Dòng báo cáo: unknown_type

  • NUL characters in text

    được giữ

    VARCHAR2 và CLOB chứa được ký tự NUL, nên giá trị được sao chép nguyên trạng.

  • text that isn't valid in its encoding

    byte lỗi thành ký tự thay thế

    Tập lệnh là UTF-8 và mọi giá trị phải là văn bản hợp lệ.

    Dòng báo cáo: invalid_utf8_replaced

  • text decoded twice (ñ)

    sao chép nguyên trạng

    Tập lệnh 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 SQL ServerTrong OracleDòng báo cáo
bitNUMBER(1) kèm CHECK 0 và 1Oracle 21c không có kiểu cột boolean; 1 và 0 giữ được giá trị trên mọi phiên bản.
char(n), varchar(n), nchar(n), nvarchar(n)VARCHAR2(n CHAR), đếm theo ký tựĐộ dài đếm theo ký tự, như nvarchar của SQL Server.
varchar(max), nvarchar(max), text, ntextVARCHAR2(4000 CHAR) khi mọi giá trị vừa 4000 byte, 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
empty strings and empty binary valuesNULLOracle lưu chuỗi rỗng dưới dạng NULL, nên giá trị từng là ' sẽ được đọc lại là NULL. Báo cáo đếm chúng theo từng cột.empty_string_null
decimal(p,s), money, smallmoneyNUMBER(p,s); money thành NUMBER(19,4)NUMBER chứa 38 chữ số, như decimal, nên mọi giá trị đều chính xác.
datetime, datetime2, smalldatetimeTIMESTAMP(p)datetime là thời gian theo đồng hồ, giống TIMESTAMP của Oracle, vốn giữ đến chín chữ số của giây. date thành DATE, kiểu cũng chứa giờ trong ngày, luôn ở nửa đêm.
datetimeoffsetTIMESTAMP WITH TIME ZONE, với độ lệch của từng giá trịOracle giữ độ lệch từ -12:00 đến +14:00; giá trị có độ lệch vượt quá -12:00 được ghi theo UTC, cùng một thời điểm.
timeINTERVAL DAY TO SECOND tính từ nửa đêmOracle không có kiểu giờ trong ngày; một khoảng thời gian tính từ nửa đêm chứa được mọi giá trị.
dates that aren't validNULLGiá trị không phải ngày sẽ thành NULL và báo cáo đếm nó.date_out_of_range
json (SQL Server 2025)CLOBCùng các giá trị JSON, mà hàm JSON của Oracle đọc được.
uniqueidentifierVARCHAR2(36)Cùng các định danh, viết bằng chữ thường.
binary, varbinary, imageRAW(n) và BLOBByte vẫn là byte.
geometry, geographyBLOB với byte riêng của SQL ServerSSMS ghi giá trị không gian theo định dạng tuần tự hóa riêng của SQL Server, được giữ nguyên từng byte.spatial_as_native
rowversion, timestampBLOB, để trốngSQL Server tự đặt phiên bản hàng và SSMS không ghi giá trị cho nó.rowversion_empty
xml, sql_variant, hierarchyid, vectorVARCHAR2 hoặc CLOB với văn bản của từng giá trịOracle không có kiểu tương đương; xml và sql_variant giữ văn bản của từng giá trị và hierarchyid giữ đường dẫn của nó, ví dụ /1/2/.type_replaced
collations that ignore case (_CI_)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, nên cột từng không phân biệt hoa thường trong SQL Server giờ phân biệt Ana và ana.case_insensitive_collation
IDENTITYGENERATED BY DEFAULT ON NULL AS IDENTITY, tiếp tục sau id lớn nhấtCác id đã sao chép được nạp nguyên trạng, và bộ đếm tiếp tục sau id lớn nhất.
CREATE SEQUENCECREATE SEQUENCE với cùng các tùy chọnSequence của Oracle hoạt động giống vậy. SSMS không ghi sequence đã chạy đến đâu, nên nó bắt đầu từ điểm lúc được tạo.
computed columnscột ảoOracle chỉ tính cột tính toán khi đọc; cột PERSISTED thành cột ảo với cùng giá trị.stored_as_virtual
computed columns with functions Oracle lacksmộ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; SSMS không ghi giá trị cho cột tính toán.generated_not_translated
defaults with functions Oracle lacks, and NEXT VALUE FORkhô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.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 Oracle lackskhô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
CHECK constraints added WITH NOCHECK or disabledkhông được tạoSQL Server không áp dụng các ràng buộc kiểm tra này, nên các hàng có thể vi phạm chúng.check_not_enforced
filtered and columnstore indexes, and indexes on CLOB columnskhông được tạoIntoSQL ghi chỉ mục b-tree 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 keyssau dữ liệu với ENABLE NOVALIDATE, rồi xác thực kèm cảnh báo về hàng mồ côiKhóa kiểm tra hàng mới ngay và được xác thực sau cùng; hàng không có hàng cha khiến khóa ở trạng thái chưa xác thực 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 DEFAULTbị bỏKhóa ngoại của Oracle chỉ hành động khi xóa, với CASCADE hoặc SET NULL.foreign_key_action_unsupported
names over 128 bytesrút ngắnTên trong Oracle 12.2 trở lên chứa 128 byte; tên trong SQL Server chứa 128 ký tự.name_shortened
foreign keys to tables the dump doesn't createkhông được tạoKhóa không thể tham chiếu tới bảng không tồn tại.foreign_key_skipped
tables on a partition schememột bảng chứa các hàng của mọi phân vùngCác hàng giữ nguyên; hãy phân vùng lại bảng trong Oracle nếu cần.partitions_dropped
temporal tables (SYSTEM_VERSIONING)hai bảng: các hàng hiện tại và lịch sửBảng và bảng lịch sử của nó được sao chép thành bảng thường; Oracle không tự giữ lịch sử.system_versioning_dropped
schemasmột schema, mỗi bảng có tên schema ở đầuTập lệnh nạp vào schema của người dùng chạy nó, nên bảng của các schema khác nhau có tên schema ở đầu; bảng trong dbo giữ nguyên tên.schemas_merged
NOT NULL columns with values that become NULLbỏ NOT NULLCột có giá trị phải chuyển thành NULL không thể giữ NOT NULL, nếu không quá trình nạp sẽ dừng.not_null_relaxed
views, functions, procedures, triggers, synonyms, types and partition functionsđược liệt kê trong báo cáoMã của chúng viết bằng T-SQL, nên được liệt kê để bạn tạo lại.not_converted_objects
scripts without CREATE TABLE (data only)kiểu suy ra từ giá trịTập lệnh chỉ có dữ liệu thì chỉ có các hàng, nên kiểu được suy ra từ giá trị.no_schema
expressions in INSERT valuesNULLTrình chuyển đổi không chạy cơ sở dữ liệu thì không tính được chúng.expression_value
types IntoSQL doesn't knowCLOBVăn bản chứa được mọi giá trị; hãy đổi kiểu sau khi nạp.unknown_type
NUL characters in textđược giữVARCHAR2 và CLOB chứa được ký tự NUL, nên giá trị được sao chép nguyên trạng.
text that isn't valid in its encodingbyte lỗi thành ký tự thay thếTập lệnh là UTF-8 và mọi giá trị phải là văn bản hợp lệ.invalid_utf8_replaced
text decoded twice (ñ)sao chép nguyên trạngTập lệnh 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 @sql_server.oracle.sql

Khó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 SQL Server để 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 đó:

  • Trong SSMS, nhấp chuột phải vào cơ sở dữ liệu, Tasks, Generate Scripts, rồi chọn các bảng. dbatools, mssql-scripter và các công cụ khác dựng trên cùng thư viện ghi ra cùng một tập lệnh.
  • Trong Advanced, đặt Types of data to script thành Schema and data. Tập lệnh chỉ có schema sẽ có bảng mà không có hàng.
  • Lưu dưới dạng Unicode, mặc định của SSMS, hoặc UTF-8: cả hai đều được đọc như nhau, và gzip cũng được.

Những gì không được chuyển đổi

Khung nhìn, hàm, thủ tục, trình kích hoạt, từ đồng nghĩa, quy tắc và chính sách bảo mật được viết bằng T-SQL. 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.

Câu hỏi về SQL Server 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.

Nó có đọc được tệp UTF-16 mà SSMS lưu không?

Có. SSMS lưu tập lệnh dạng UTF-16 theo mặc định, và trình chuyển đổi đọc UTF-16 và UTF-8 như nhau, có nén gzip hay không, với GO giữa các lô.

Tập lệnh có thể đến từ những phiên bản SQL Server nào?

Tập lệnh do SSMS, dbatools hoặc mssql-scripter ghi từ SQL Server 2017 trở lên. Mọi tập lệnh thử nghiệm đến từ SQL Server 2017, 2022 và 2025 và được so với nguồn từng ô một.

Giá trị IDENTITY có được giữ không?

Có. Cột IDENTITY 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. Sequence được tạo với cùng các tùy chọn.

money, datetimeoffset và các kiểu SQL Server khác sẽ ra sao?

bit thành NUMBER(1), datetime2 thành TIMESTAMP với mọi chữ số, datetimeoffset thành TIMESTAMP WITH TIME ZONE với độ lệch của nó, và nvarchar(max) thành CLOB khi giá trị không vừa VARCHAR2. Chuỗi rỗng thành NULL, vì Oracle lưu chúng như vậy, và báo cáo đếm chúng.

Còn thủ tục, trình kích hoạt và khung nhìn 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 tập lệnh 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ố.