本文へスキップ
IntoSQL ホーム

SQL Server を Oracle に変換

SSMS の「スクリプトの生成」でスキーマとデータを含めて書き出したスクリプト (.sql または .sql.gz、UTF-16 または UTF-8) をドロップすると、同じテーブル、キー、インデックス、データを持つ Oracle スクリプトをダウンロードできます。Oracle がそのまま保持できない値と、引き継がないオブジェクトは、すべてレポートに記載されます。

ファイル
sqlshop_2024_sqlserver.sqlサンプルファイル、11 KB
データベース

18 行を変換、修正 2 件、却下なし

表示

shop_2024_sqlserver.sql のテーブルSQL Server のダンプ · SQL Server Management Objects で作成 · utf-8

  • ordersORDERS として書き出し10 行1
    11 列
    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)
  • customersCUSTOMERS として書き出し8 行1
    8 列
    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)

未変換

  • ビュー paid_orders
  • トリガー orders_no_negative

これらはデータベースごとに独自の言語で書かれます。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;

修正

  1. orders の "total_with_tax" はソースでは保存されますが、Oracle では読み取り時に計算します。
  2. customers の "row_version" は SQL Server が自動で設定する行バージョンです。ダンプにはその値がないため、RAW(8) にして空のままにします。

確認が必要

  • ソースでは 6 個のテキスト列が大文字と小文字を区別せずに比較します。Oracle は厳密に比較するため、一意キーや検索の動作が変わる場合があります。 必要な列には、大文字と小文字を区別しない照合順序か列の型を使ってください。
  • 2 件のビュー、トリガー、ルーチン、イベントは変換されません。レポートにそれぞれ記載しています。 Oracle で手動で作り直してください。
  • orders のチェック制約 check1 は Oracle 用に書き換えられないため (function isjson)、作成しません。 必要であれば、手動でチェック制約を書いてください。
  • orders のインデックス idx_orders_pending は Oracle 用に書き換えられない式を使っているため (filtered index)、作成しません。 クエリに必要なら、手動でインデックスを作成してください。
  • orders の "order_ref" のデフォルト値は Oracle 用に書き換えられないため (function uuid)、列にデフォルト値はありません。 新しい行に必要なら、手動でデフォルト値を追加してください。

ファイルはこのコンピューター上で変換され、アップロードされることはありません。

その他のサンプル:

SQL Server から Oracle で変わること

各行はコンバーターが適用するルールです。ルールによってデータが変わったときにレポートに書かれる行も示します。

  • bit

    0 と 1 の CHECK 付きの NUMBER(1)

    Oracle 21c には boolean 列型がありません。1 と 0 ならどのバージョンでも値を保てます。

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

    VARCHAR2(n CHAR)、文字数で数える

    長さは SQL Server の nvarchar と同じく文字数で数えます。

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

    すべての値が 4000 バイトに収まれば VARCHAR2(4000 CHAR)、それ以外は CLOB

    VARCHAR2 はデフォルトで 4000 バイトまでで、Oracle は CLOB にインデックスを作れません。そのためテキストは値が収まれば VARCHAR2 のまま、収まらなければ CLOB になります。

    レポートの行: text_as_lob

  • empty strings and empty binary values

    NULL

    Oracle は空文字列を NULL として保存するため、' だった値は NULL として読み出されます。レポートで列ごとにその数を示します。

    レポートの行: empty_string_null

  • decimal(p,s), money, smallmoney

    NUMBER(p,s)、money は NUMBER(19,4)

    NUMBER は decimal と同じく 38 桁を保持できるため、すべての値が正確です。

  • datetime, datetime2, smalldatetime

    TIMESTAMP(p)

    datetime は時計が示す時刻で、秒の小数を 9 桁まで保てる Oracle の TIMESTAMP と同じです。date は DATE になり、時刻も持ちますが午前 0 時のままです。

  • datetimeoffset

    TIMESTAMP WITH TIME ZONE、各値のオフセット付き

    Oracle が保持できるオフセットは -12:00 から +14:00 までです。-12:00 を超えるオフセットの値は UTC で書き出し、同じ時点を保ちます。

  • time

    午前0時からの INTERVAL DAY TO SECOND

    Oracle には時刻だけの型がありません。午前 0 時からの interval ならすべての値を保持できます。

  • dates that aren't valid

    NULL

    日付ではない値は NULL になり、レポートで件数を示します。

    レポートの行: date_out_of_range

  • json (SQL Server 2025)

    CLOB

    JSON の値は同じで、Oracle の JSON 関数で読めます。

  • uniqueidentifier

    VARCHAR2(36)

    同じ識別子を小文字で書き出します。

  • binary, varbinary, image

    RAW(n) と BLOB

    バイトはバイトのままです。

  • geometry, geography

    SQL Server 独自のバイト列を持つ BLOB

    SSMS は空間値を SQL Server のシリアル化形式で書き出し、それをバイト単位でそのまま保ちます。

    レポートの行: spatial_as_native

  • rowversion, timestamp

    BLOB、空

    行バージョンは SQL Server が自動で設定するもので、SSMS はその値をスクリプトに含めません。

    レポートの行: rowversion_empty

  • xml, sql_variant, hierarchyid, vector

    各値のテキストを持つ VARCHAR2 または CLOB

    Oracle には同等の型がありません。xml と sql_variant は各値のテキストを、hierarchyid は /1/2/ のようなパスを保ちます。

    レポートの行: type_replaced

  • collations that ignore case (_CI_)

    厳密な比較

    Oracle は指定がない限りテキストを厳密に比較するため、SQL Server で大文字と小文字を区別しなかった列でも、Ana と ana を区別するようになります。

    レポートの行: case_insensitive_collation

  • IDENTITY

    GENERATED BY DEFAULT ON NULL AS IDENTITY、最大の ID の後から継続

    コピーした ID はそのまま読み込み、カウンターは最大の ID の後から続きます。

  • CREATE SEQUENCE

    同じオプションの CREATE SEQUENCE

    Oracle のシーケンスも同じように動作します。SSMS はシーケンスの現在位置をスクリプトに含めないため、作成時の値から始まります。

  • computed columns

    仮想列

    Oracle は生成列を読み取り時にのみ計算します。PERSISTED の列は同じ値の仮想列になります。

    レポートの行: stored_as_virtual

  • computed columns with functions Oracle lacks

    普通の列

    書き換えられない式は、普通の列とレポートの 1 行になります。SSMS は計算列の値をスクリプトに含めません。

    レポートの行: generated_not_translated

  • defaults with functions Oracle lacks, and NEXT VALUE FOR

    デフォルト値なし

    書き換えられないデフォルト値は含めず、レポートに記載します。

    レポートの行: default_not_translated

  • CHECK constraints

    変換済み

    チェック制約は同じで、各行の読み込み時に検証します。

  • CHECK constraints with functions Oracle lacks

    作成しない

    書き換えられないチェック制約は含めず、レポートに記載します。

    レポートの行: check_skipped

  • CHECK constraints added WITH NOCHECK or disabled

    作成しない

    SQL Server はこれらのチェックを適用していないため、行が違反している可能性があります。

    レポートの行: check_not_enforced

  • filtered and columnstore indexes, and indexes on CLOB columns

    作成しない

    IntoSQL が書き出すのは列全体に対する b-tree インデックスです。その他は読み込み後に作り直してください。

    レポートの行: index_skipped

  • foreign keys

    データの後に ENABLE NOVALIDATE で作成してから検証し、孤立した行があれば警告

    キーは新しい行をすぐにチェックし、最後に検証します。親のない行があれば、読み込みを止めずにキーを未検証のまま残して警告します。

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

    削除

    Oracle の外部キーが動作するのは削除時だけで、CASCADE か SET NULL のみです。

    レポートの行: foreign_key_action_unsupported

  • names over 128 bytes

    短縮

    Oracle 12.2 以降の名前は 128 バイトまでです。SQL Server の名前は 128 文字までです。

    レポートの行: name_shortened

  • foreign keys to tables the dump doesn't create

    作成しない

    キーは存在しないテーブルを参照できません。

    レポートの行: foreign_key_skipped

  • tables on a partition scheme

    すべてのパーティションの行を持つ 1 つのテーブル

    行は同じです。必要なら Oracle でもう一度テーブルをパーティション分割してください。

    レポートの行: partitions_dropped

  • temporal tables (SYSTEM_VERSIONING)

    2 つのテーブル: 現在の行と履歴

    テーブルとその履歴テーブルは普通のテーブルとしてコピーします。Oracle は履歴を自動では保持しません。

    レポートの行: system_versioning_dropped

  • schemas

    1 つのスキーマ、テーブル名の先頭にスキーマ名

    スクリプトは実行したユーザーのスキーマに読み込まれるため、別のスキーマのテーブルには先頭にスキーマ名が付きます。dbo のテーブルは名前を保ちます。

    レポートの行: schemas_merged

  • NOT NULL columns with values that become NULL

    NOT NULL を削除

    値を NULL にする必要があった列は、NOT NULL を保てません。保つと読み込みが止まります。

    レポートの行: not_null_relaxed

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

    レポートに記載

    コードが T-SQL で書かれているため、作り直せるよう一覧にします。

    レポートの行: not_converted_objects

  • scripts without CREATE TABLE (data only)

    値から読み取った型

    データのみのスクリプトには行しかないため、型は値から決まります。

    レポートの行: no_schema

  • expressions in INSERT values

    NULL

    データベースを実行しないコンバーターでは、これらを評価できません。

    レポートの行: expression_value

  • types IntoSQL doesn't know

    CLOB

    テキストはどんな値も保持できます。読み込み後に型を変更してください。

    レポートの行: unknown_type

  • NUL characters in text

    保持

    VARCHAR2 と CLOB は NUL 文字を保持できるため、値はそのままコピーします。

  • text that isn't valid in its encoding

    不正なバイトを置換文字に

    スクリプトは UTF-8 なので、すべての値が有効なテキストである必要があります。

    レポートの行: invalid_utf8_replaced

  • text decoded twice (ñ)

    そのままコピー

    スクリプトにはまさにこの文字が含まれているため、そのままコピーし、レポートで指摘します。

    レポートの行: mojibake_suspected

SQL Server ではOracle ではレポートの行
bit0 と 1 の CHECK 付きの NUMBER(1)Oracle 21c には boolean 列型がありません。1 と 0 ならどのバージョンでも値を保てます。
char(n), varchar(n), nchar(n), nvarchar(n)VARCHAR2(n CHAR)、文字数で数える長さは SQL Server の nvarchar と同じく文字数で数えます。
varchar(max), nvarchar(max), text, ntextすべての値が 4000 バイトに収まれば VARCHAR2(4000 CHAR)、それ以外は CLOBVARCHAR2 はデフォルトで 4000 バイトまでで、Oracle は CLOB にインデックスを作れません。そのためテキストは値が収まれば VARCHAR2 のまま、収まらなければ CLOB になります。text_as_lob
empty strings and empty binary valuesNULLOracle は空文字列を NULL として保存するため、' だった値は NULL として読み出されます。レポートで列ごとにその数を示します。empty_string_null
decimal(p,s), money, smallmoneyNUMBER(p,s)、money は NUMBER(19,4)NUMBER は decimal と同じく 38 桁を保持できるため、すべての値が正確です。
datetime, datetime2, smalldatetimeTIMESTAMP(p)datetime は時計が示す時刻で、秒の小数を 9 桁まで保てる Oracle の TIMESTAMP と同じです。date は DATE になり、時刻も持ちますが午前 0 時のままです。
datetimeoffsetTIMESTAMP WITH TIME ZONE、各値のオフセット付きOracle が保持できるオフセットは -12:00 から +14:00 までです。-12:00 を超えるオフセットの値は UTC で書き出し、同じ時点を保ちます。
time午前0時からの INTERVAL DAY TO SECONDOracle には時刻だけの型がありません。午前 0 時からの interval ならすべての値を保持できます。
dates that aren't validNULL日付ではない値は NULL になり、レポートで件数を示します。date_out_of_range
json (SQL Server 2025)CLOBJSON の値は同じで、Oracle の JSON 関数で読めます。
uniqueidentifierVARCHAR2(36)同じ識別子を小文字で書き出します。
binary, varbinary, imageRAW(n) と BLOBバイトはバイトのままです。
geometry, geographySQL Server 独自のバイト列を持つ BLOBSSMS は空間値を SQL Server のシリアル化形式で書き出し、それをバイト単位でそのまま保ちます。spatial_as_native
rowversion, timestampBLOB、空行バージョンは SQL Server が自動で設定するもので、SSMS はその値をスクリプトに含めません。rowversion_empty
xml, sql_variant, hierarchyid, vector各値のテキストを持つ VARCHAR2 または CLOBOracle には同等の型がありません。xml と sql_variant は各値のテキストを、hierarchyid は /1/2/ のようなパスを保ちます。type_replaced
collations that ignore case (_CI_)厳密な比較Oracle は指定がない限りテキストを厳密に比較するため、SQL Server で大文字と小文字を区別しなかった列でも、Ana と ana を区別するようになります。case_insensitive_collation
IDENTITYGENERATED BY DEFAULT ON NULL AS IDENTITY、最大の ID の後から継続コピーした ID はそのまま読み込み、カウンターは最大の ID の後から続きます。
CREATE SEQUENCE同じオプションの CREATE SEQUENCEOracle のシーケンスも同じように動作します。SSMS はシーケンスの現在位置をスクリプトに含めないため、作成時の値から始まります。
computed columns仮想列Oracle は生成列を読み取り時にのみ計算します。PERSISTED の列は同じ値の仮想列になります。stored_as_virtual
computed columns with functions Oracle lacks普通の列書き換えられない式は、普通の列とレポートの 1 行になります。SSMS は計算列の値をスクリプトに含めません。generated_not_translated
defaults with functions Oracle lacks, and NEXT VALUE FORデフォルト値なし書き換えられないデフォルト値は含めず、レポートに記載します。default_not_translated
CHECK constraints変換済みチェック制約は同じで、各行の読み込み時に検証します。
CHECK constraints with functions Oracle lacks作成しない書き換えられないチェック制約は含めず、レポートに記載します。check_skipped
CHECK constraints added WITH NOCHECK or disabled作成しないSQL Server はこれらのチェックを適用していないため、行が違反している可能性があります。check_not_enforced
filtered and columnstore indexes, and indexes on CLOB columns作成しないIntoSQL が書き出すのは列全体に対する b-tree インデックスです。その他は読み込み後に作り直してください。index_skipped
foreign keysデータの後に ENABLE NOVALIDATE で作成してから検証し、孤立した行があれば警告キーは新しい行をすぐにチェックし、最後に検証します。親のない行があれば、読み込みを止めずにキーを未検証のまま残して警告します。
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT削除Oracle の外部キーが動作するのは削除時だけで、CASCADE か SET NULL のみです。foreign_key_action_unsupported
names over 128 bytes短縮Oracle 12.2 以降の名前は 128 バイトまでです。SQL Server の名前は 128 文字までです。name_shortened
foreign keys to tables the dump doesn't create作成しないキーは存在しないテーブルを参照できません。foreign_key_skipped
tables on a partition schemeすべてのパーティションの行を持つ 1 つのテーブル行は同じです。必要なら Oracle でもう一度テーブルをパーティション分割してください。partitions_dropped
temporal tables (SYSTEM_VERSIONING)2 つのテーブル: 現在の行と履歴テーブルとその履歴テーブルは普通のテーブルとしてコピーします。Oracle は履歴を自動では保持しません。system_versioning_dropped
schemas1 つのスキーマ、テーブル名の先頭にスキーマ名スクリプトは実行したユーザーのスキーマに読み込まれるため、別のスキーマのテーブルには先頭にスキーマ名が付きます。dbo のテーブルは名前を保ちます。schemas_merged
NOT NULL columns with values that become NULLNOT NULL を削除値を NULL にする必要があった列は、NOT NULL を保てません。保つと読み込みが止まります。not_null_relaxed
views, functions, procedures, triggers, synonyms, types and partition functionsレポートに記載コードが T-SQL で書かれているため、作り直せるよう一覧にします。not_converted_objects
scripts without CREATE TABLE (data only)値から読み取った型データのみのスクリプトには行しかないため、型は値から決まります。no_schema
expressions in INSERT valuesNULLデータベースを実行しないコンバーターでは、これらを評価できません。expression_value
types IntoSQL doesn't knowCLOBテキストはどんな値も保持できます。読み込み後に型を変更してください。unknown_type
NUL characters in text保持VARCHAR2 と CLOB は NUL 文字を保持できるため、値はそのままコピーします。
text that isn't valid in its encoding不正なバイトを置換文字にスクリプトは UTF-8 なので、すべての値が有効なテキストである必要があります。invalid_utf8_replaced
text decoded twice (ñ)そのままコピースクリプトにはまさにこの文字が含まれているため、そのままコピーし、レポートで指摘します。mojibake_suspected

スクリプトを Oracle に読み込む

スクリプトはテーブルを作成して行をコピーしてから、キー、インデックス、外部キーを追加します。そのため読み込みが速く、最初のエラーで止まります。

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

外部キーは ENABLE NOVALIDATE で追加するため新しい行はすぐにチェックされ、その後に検証します。古い行が存在しない行を参照していれば、途中で失敗する代わりに、どの制約かをスクリプトが示し、その制約は未検証のまま残します。

大きなダンプでは、データベースと同じマシンで SQL*Plus を実行してください。スクリプトは 100 行ごとにコミットします。実行するユーザーには CREATE TABLE、CREATE SEQUENCE、CREATE TRIGGER、CREATE PROCEDURE の権限と、表領域の割り当てが必要です。

SQL Server を最適な方法でダンプする

コンバーターはダンプの内容を読み取ります。次のオプションを使うと、より多くのデータがダンプに残ります。

  • SSMS でデータベースを右クリックし、[タスク]、[スクリプトの生成] を選んでテーブルを選択します。dbatools、mssql-scripter など同じライブラリを使うツールも同じスクリプトを書き出します。
  • [詳細設定] で [スクリプトを作成するデータの種類] を [スキーマとデータ] にします。スキーマだけのスクリプトでは、テーブルに行がありません。
  • SSMS のデフォルトである Unicode、または UTF-8 で保存します。どちらも同じように読み込め、gzip も使えます。

変換されないもの

ビュー、関数、プロシージャ、トリガー、シノニム、ルール、セキュリティポリシーは T-SQL で書かれています。黙って削除することはなく、レポートに名前で一覧するので、Oracle 向けに書き直せます。

SQL Server から Oracle への変換に関する質問

ここに答えがない場合は、お問い合わせページからご連絡ください。担当者が返信します。 お問い合わせページ

ダンプはアップロードされますか?

いいえ。コンバーターはブラウザ上で動作し、ダンプをディスクから少しずつ読み込むため、ダンプがコンピューターの外に出ることはありません。デスクトップアプリとコマンドラインも、お使いのコンピューター上で変換します。

ダンプはどのくらいの大きさまで扱えますか?

コンバーターはダンプ全体をメモリに保持しません。ファイルを範囲ごとに 2 回読み、読みながらスクリプトを書き出します。数 GB のダンプも、ブラウザ、デスクトップアプリ、コマンドラインで変換できます。

SSMS が保存する UTF-16 のファイルを読めますか?

はい。SSMS はデフォルトでスクリプトを UTF-16 で保存しますが、コンバーターは UTF-16 も UTF-8 も、gzip の有無にかかわらず、バッチ間の GO を含めて同じように読み込みます。

どの SQL Server バージョンのスクリプトに対応していますか?

SQL Server 2017 以降から SSMS、dbatools、mssql-scripter で書き出したスクリプトです。すべてのテスト用スクリプトは SQL Server 2017、2022、2025 で作成し、ソースとセル単位で比較しています。

IDENTITY の値は保持されますか?

はい。IDENTITY 列は identity 列になり、すべての行が ID を保ち、次の ID は最大の ID の後から続きます。シーケンスは同じオプションで作成します。

money、datetimeoffset など SQL Server の型はどうなりますか?

bit は NUMBER(1)、datetime2 はすべての桁を持つ TIMESTAMP、datetimeoffset はオフセット付きの TIMESTAMP WITH TIME ZONE、nvarchar(max) は値が VARCHAR2 に収まらない場合に CLOB になります。空文字列は Oracle の保存方法に合わせて NULL になり、レポートで件数を示します。

プロシージャ、トリガー、ビューはどうなりますか?

データベースごとに独自の言語で書かれるため、変換はせず、レポートに名前で一覧します。

スクリプトはどの Oracle バージョンで読み込めますか?

Oracle 19c 以降です。すべてのテスト用スクリプトを 21c と 23ai で読み込み、問題があれば最初のエラーで止まります。