SQL Server を Oracle に変換
SSMS の「スクリプトの生成」でスキーマとデータを含めて書き出したスクリプト (.sql または .sql.gz、UTF-16 または UTF-8) をドロップすると、同じテーブル、キー、インデックス、データを持つ Oracle スクリプトをダウンロードできます。Oracle がそのまま保持できない値と、引き継がないオブジェクトは、すべてレポートに記載されます。
18 行を変換、修正 2 件、却下なし
shop_2024_sqlserver.sql のテーブルSQL Server のダンプ · SQL Server Management Objects で作成 · utf-8
ordersORDERS として書き出し10 行1
11 列 ID NUMBER(10) not null CUSTOMER_ID NUMBER(10) not null STATUS VARCHAR2(10 CHAR) not null TOTAL NUMBER(19,4) not null ITEMS NUMBER(3) 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) customersCUSTOMERS として書き出し8 行1
8 列 ID NUMBER(10) not null NAME VARCHAR2(100 CHAR) not null EMAIL VARCHAR2(200 CHAR) not null COUNTRY VARCHAR2(2 CHAR) not null IS_ACTIVE NUMBER(1) not null SIGNED_UP DATE CREATED_AT TIMESTAMP(0) WITH TIME ZONE not null ROW_VERSION RAW(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;
修正
- orders の "total_with_tax" はソースでは保存されますが、Oracle では読み取り時に計算します。
- 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 では | レポートの行 |
|---|---|---|
| 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)、それ以外は CLOBVARCHAR2 はデフォルトで 4000 バイトまでで、Oracle は CLOB にインデックスを作れません。そのためテキストは値が収まれば VARCHAR2 のまま、収まらなければ CLOB になります。 | text_as_lob |
| empty strings and empty binary values | NULLOracle は空文字列を 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 SECONDOracle には時刻だけの型がありません。午前 0 時からの interval ならすべての値を保持できます。 | |
| dates that aren't valid | NULL日付ではない値は NULL になり、レポートで件数を示します。 | date_out_of_range |
| json (SQL Server 2025) | CLOBJSON の値は同じで、Oracle の JSON 関数で読めます。 | |
| uniqueidentifier | VARCHAR2(36)同じ識別子を小文字で書き出します。 | |
| binary, varbinary, image | RAW(n) と BLOBバイトはバイトのままです。 | |
| geometry, geography | SQL Server 独自のバイト列を持つ BLOBSSMS は空間値を SQL Server のシリアル化形式で書き出し、それをバイト単位でそのまま保ちます。 | spatial_as_native |
| rowversion, timestamp | BLOB、空行バージョンは 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 |
| IDENTITY | GENERATED 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 |
| 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 |
スクリプトを 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 で読み込み、問題があれば最初のエラーで止まります。