SQL Server Migration Assistant for Oracle  による Oracle Database から Azure SQL Database への移行検証～Oracle データ操作言語( DML )文編～


## 概要

### 本記事の位置付けについて

Oracle Database から Azure SQL Database へ SQL Server Migration Assistant for Oracle （SSMA）によるプログラム移行検証結果の一部である。次の記事にて個別機能別記事へのリンクを整理している。

- [SQL Server Migration Assistant for Oracle による Oracle Database から Azure SQL Database への移行検証記事のまとめ - Qiita](https://qiita.com/manabian/items/0ec96b66033a7bd03a25)


### データ操作言語( DML )文について

データ操作言語( DML )文について、Oracle Database ドキュメントにて、次のように記載されている。

> Oracle Database表のデータを追加、変更および削除します。

引用元：[3 DML文とトランザクションについて (oracle.com)](https://docs.oracle.com/cd/E82638_01/tdddg/dml-and-transactions.html#GUID-3BE9310F-0AC5-4F75-9AA7-B7A843C14E2F)

### 参考リンク

- ホワイトペーパー
    - Oracle to SQL Server Migration Handbook v 2.0

## Azure SQL Database への移行

### SSMA による変換

基本的な DDL 文であれば、自動変換される。

Oracle 方言で記載されている場合には、issues となる場合がある。

### 移行方針

特になし。

### 変換例

#### 事前準備

##### Oracle Database の事前準備

```sql
CREATE TABLE dml_test_001 
(
    ID INT
    ,NAME NVARCHAR2(50)
)
/
CREATE TABLE dml_test_002
(
    ID INT
    ,NAME NVARCHAR2(50)
)
```

#### 変換例 1 INSERT 文

##### Oracle Database のコード

```sql
INSERT INTO dml_test_001
SELECT
    *
    FROM (
        SELECT 1 AS ID, 'AAA' AS NAME FROM DUAL
        UNION ALL
        SELECT 2 AS ID, 'BBB' AS NAME FROM DUAL
        UNION ALL
        SELECT 3 AS ID, 'DDD' AS NAME FROM DUAL
    );
```

##### Azure SQL Database への変換

SSMA により次のように変換される。

```sql
INSERT SSMA.DML_TEST_001(ID, NAME)
   SELECT fci.ID, fci.NAME
   FROM 
      (
         SELECT 1 AS ID, 'AAA' AS NAME
          UNION ALL
         SELECT 2 AS ID, 'BBB' AS NAME
          UNION ALL
         SELECT 3 AS ID, 'DDD' AS NAME
      )  AS fci
GO
```

#### 変換例 2 UPDATE 文

##### Oracle Database のコード

```sql
UPDATE  SSMA.dml_test_001
SET
    NAME = 'CCC'
WHERE 
    ID = 3;
```

##### Azure SQL Database への変換

SSMA により次のように変換される。

```sql
UPDATE SSMA.DML_TEST_001
   SET 
      NAME = 'CCC'
WHERE DML_TEST_001.ID = 3
GO
```

#### 変換例 3 MERGE 文

##### Oracle Database のコード

```sql
MERGE INTO dml_test_002 tgt
USING dml_test_001 src 
ON ( tgt.id = src.id )
WHEN MATCHED THEN UPDATE
SET tgt.name = src.name
WHEN NOT MATCHED THEN
INSERT (
    tgt.id,
    tgt.name )
VALUES
    ( src.id,
      src.name );
```

##### Azure SQL Database への変換

SSMA により次のように変換される。

```sql
MERGE INTO SSMA.DML_TEST_002  AS TGT
   USING SSMA.DML_TEST_001  AS SRC
   ON(TGT.ID = SRC.ID)
   WHEN MATCHED THEN 
      UPDATE 
         SET 
            NAME = SRC.NAME
   WHEN NOT MATCHED BY TARGET 
      THEN INSERT (ID, NAME)
         VALUES (SRC.ID, SRC.NAME)
;
GO
```

#### 変換例 4 DELETE 文

##### Oracle Database のコード

```sql
DELETE dml_test_002;
```

##### Azure SQL Database への変換

SSMA により次のように変換される。

```sql
DELETE SSMA.DML_TEST_002
GO
```

#### 変換例 5 TRUNCATE 文

##### Oracle Database のコード

```sql
TRUNCATE TABLE dml_test_001;
```

##### Azure SQL Database への変換

SSMA により次のように変換される。

```sql
TRUNCATE TABLE SSMA.DML_TEST_001
GO
```

#### 変換例 6 RETURNING 句 の利用

##### Oracle Database のコード

```sql
DECLARE
    v1 dml_test_001.ID%TYPE;
    v2 dml_test_001.NAME%TYPE;
BEGIN
    INSERT INTO dml_test_001(ID,NAME)
    VALUES(1, 'aaa')
    RETURNING ID, NAME INTO v1, v2;
    DBMS_OUTPUT.PUT_LINE('ID:' || v1 || ' NAME:' || v2);
END;
```

##### Azure SQL Database への変換

SSMA により次のように変換される。

```sql
BEGIN

   DECLARE
      @V1 numeric(38, 0), 
      @V2 nvarchar(50)

   DECLARE
      @temp_table TABLE 
      (
         V1 numeric(38, 0), 
         V2 nvarchar(50)
      )

   /*
   *   SSMA warning messages:
   *   O2SS0058: OUTPUT clauses might return different results in SQL Server when using triggers.
   */

   INSERT SSMA.DML_TEST_001(ID, NAME)
      OUTPUT INSERTED.ID, INSERTED.NAME
         INTO @temp_table(V1, V2)
      VALUES (1, 'aaa')

   SELECT @V1 = NULL, @V2 = NULL

   SELECT @V1 = V1, @V2 = V2
   FROM @temp_table

   PRINT 'ID:' + ISNULL(CAST(@V1 AS nvarchar(max)), '') + ' NAME:' + ISNULL(@V2, '')

END
GO
```