SQL Server Migration Assistant for Oracle  による Oracle Database から Azure SQL Database への移行検証～Oracle 関数編～


## 概要

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

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)

### システム関数について

関数について、Oracle Database ドキュメントにて、次のように記載されている。

> データ項目を操作し、結果を戻すという点で演算子に似ています。ファンクションと演算子は引数を指定する書式が異なります。

引用元；[7 ファンクション (oracle.com)](https://docs.oracle.com/cd/F19136_01/sqlrf/Functions.html#GUID-D079EFD3-C683-441F-977E-2C9503089982)

システムに事前に定義されている関数を、システム関数と呼ばれることがある。Oracle Database にてサポートされている関数については、次のドキュメントからたどり着くことができる。

- [7 ファンクション (oracle.com)](https://docs.oracle.com/cd/F19136_01/sqlrf/Functions.html#GUID-D079EFD3-C683-441F-977E-2C9503089982)

### 参考リンク

- ホワイトペーパー
    - Guide to Migrating from Oracle to SQL Server 2014 and Azure SQL Database
    - Oracle to SQL Server Migration Handbook v 2.0

## Azure SQL Database への移行

### SSMA による変換

Oracle Database のシステム関数は、T-SQL のシステム関数、あるいは、SSMA_ORACLE スキーマの関数に置換され、完全置換となる場合と前提条件付置換となる場合がある。引数の数を動的に指定できる場合や複数のデータ型を関数である場合には、そのケースに応じた関数に置換される。`INSTR4_VARCHAR`という関数では、引数が４つあり、引数のデータ型が varchar 型であることを指している。

SSMA_ORACLE スキーマの関数を用いる場合には、性能の観点で課題となることがあるため、基本的にはシステム関数に再置換することが望ましい。

SSMA_ORACLE スキーマの関数へ置換される関数について、次のドキュメントに記載されている。

- Migrating-Oracle-to-SQL-Server-2014-and-Azure-SQL-DB

### 移行方針

特になし

### 分析関数の置換方針

次の関数が置換されることを確認

- LAG
- LEAD
- FIRST_VALUE
- LAST_VALUE


```sql
WITH src AS (
SELECT '2020' AS YEAR, 100 AS VALUE FROM DUAL
UNION ALL
SELECT '2021' AS YEAR, 200 AS VALUE FROM DUAL
UNION ALL
SELECT '2022' AS YEAR, 300 AS VALUE FROM DUAL
)
SELECT
    YEAR
    ,VALUE
    ,LAG(VALUE, 1, 0 ) OVER (ORDER BY YEAR) AS lag_value
    ,LEAD(VALUE, 1, 0 ) OVER (ORDER BY YEAR) AS lead_value
    ,FIRST_VALUE(VALUE) OVER (ORDER BY YEAR ASC ROWS UNBOUNDED PRECEDING) AS first_value
    ,LAST_VALUE(VALUE) OVER (ORDER BY YEAR ASC ROWS UNBOUNDED PRECEDING) AS first_value
    FROM
        src
```

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

```sql
WITH src AS (
SELECT '2020' AS YEAR, 100 AS VALUE FROM DUAL
UNION ALL
SELECT '2021' AS YEAR, 200 AS VALUE FROM DUAL
UNION ALL
SELECT '2022' AS YEAR, 300 AS VALUE FROM DUAL
)
SELECT
    YEAR
    ,VALUE
    ,LAG(VALUE, 1, 0 ) OVER (ORDER BY YEAR) AS lag_value
    ,LEAD(VALUE, 1, 0 ) OVER (ORDER BY YEAR) AS lead_value
    ,FIRST_VALUE(VALUE) OVER (ORDER BY YEAR ASC ROWS UNBOUNDED PRECEDING) AS first_value
    ,LAST_VALUE(VALUE) OVER (ORDER BY YEAR ASC ROWS UNBOUNDED PRECEDING) AS first_value
    FROM
        src;
```

次の関数は変換が実施されることを確認できず。

- CUME_DIST
- PERCENTILE_DISC
- PERCENTILE_RANK
- PERCENTILE_COST

## Azure SQL Database にて SSMA により自動置換されない関数への対応方針

### 置換方針概要

#### ケース 1 データベース文字セットに利用されている場合

`UTL_FILE` パッケージにてファイル出力を実施する場合に、データベース文字セットを指定する場合に用いられることがある。Azure Data Factory などの他ツールで文字コードを指定してファイル出力するようにする。

```sql
UTL_FILE.PUT(FILE_PATH,CONVERT('あいうえお','JA16SJIS'));
```

日本語を用いたシステムでは、次の文字セットが利用されることがある。

- JA16EUC
- JA16SJIS

参考：[A.4.1 推奨するデータベース文字セット](https://docs.oracle.com/cd/F19136_01/nlspg/appendix-A-locale-data.html#GUID-9529D1B5-7366-4195-94B5-0F90F3B472E1)


### SUBSTRB 関数の置換方針

### 置換方針概要

Oracle Database における SUBSTRB 関数相当の機能が Azure SQL Database に存在していないため、手動変換を実施する必要がある。

次のクエリで確認ができる Oracle Database のマルチバイト・キャラクタセットに、Azure SQL Database の照合順序を合わせる必要がある。`NLS_CHARACTERSET`が`UTF-8`（`AL32UTF8`）になっていることが多い。`UTF-8`が設定されている場合には、アルファベット（1byte）と日本語の文字（3byte）ではバイト数が異なる。 SUBSTRB 関数にて、取得想定の文字に対して指定するバイト数が不足している場合には、想定通りに取得できないバイト数分の空白で埋められる。`substrb('あa', 2, 3)`を実行すると、`あ`の値を適切に取得できずに`  a`というリターン値が返ってくる。

```sql
SELECT
    parameter,
    value
FROM
    nls_database_parameters
WHERE
    parameter IN ( 'NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET' )
ORDER BY
    parameter;
```

| PARAMETER              | VALUE     |
| ---------------------- | --------- |
| NLS_CHARACTERSET       | AL32UTF8  |
| NLS_NCHAR_CHARACTERSET | AL16UTF16 |