# 画面設計書 223-カスタムエラー

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおけるカスタムエラーメッセージ管理機能の設計仕様を定義する。SQL Serverのsys.messagesに登録されるユーザー定義エラーメッセージの取得・作成・削除・コピー機能を提供するCLIインターフェースである。

### 本画面の処理概要

本機能は、SQL Serverのsys.messagesシステムカタログに格納されるカスタムエラーメッセージ（ユーザー定義メッセージ）を管理する。カスタムエラーメッセージは、sp_addmessageで追加されるメッセージID 50001以上のユーザー定義メッセージであり、アプリケーションやストアドプロシージャでRAISERRORを使用して発生させることができる。

**業務上の目的・背景**：エンタープライズアプリケーションでは、一貫したエラーメッセージ体系が保守性・運用性向上に不可欠である。カスタムエラーメッセージにより、「Customer record not found」や「Data validation failed for field X」といった業務固有のエラーを定義できる。マイグレーション時にはソースサーバーのカスタムエラーを移行先に複製する必要があり、本機能はその一括処理を自動化する。また、監査・棚卸し目的でのエラーメッセージ一覧取得にも活用される。

**画面へのアクセス方法**：PowerShellコンソールから以下のコマンドを実行することでアクセスする。
- `Get-DbaCustomError` - カスタムエラーの取得
- `New-DbaCustomError` - カスタムエラーの作成
- `Remove-DbaCustomError` - カスタムエラーの削除
- `Copy-DbaCustomError` - カスタムエラーのコピー（インスタンス間）

**主要な操作・処理内容**：
1. 既存カスタムエラーメッセージの一覧取得
2. 新規カスタムエラーメッセージの作成（メッセージID、重大度、テキスト指定）
3. 不要なカスタムエラーメッセージの削除
4. インスタンス間でのカスタムエラーメッセージの移行・同期
5. 多言語対応（複数言語バージョンのメッセージ管理）

**画面遷移**：本機能はCLIコマンドであり、画面遷移は存在しない。ただし、マイグレーションワークフローの一部として、`Start-DbaMigration`から呼び出されることがある。

**権限による表示制御**：カスタムエラーの取得には特別な権限は不要。追加・削除にはsysadminロールまたはserveradmin固定サーバーロールのメンバーシップが必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | Get-DbaCustomError | 主機能 | カスタムエラーメッセージの取得 |
| - | New-DbaCustomError | 主機能 | カスタムエラーメッセージの作成 |
| - | Remove-DbaCustomError | 主機能 | カスタムエラーメッセージの削除 |
| - | Copy-DbaCustomError | 主機能 | カスタムエラーメッセージのコピー |
| - | Start-DbaMigration | 関連機能 | 全体マイグレーションの一部として呼び出し |
| - | Connect-DbaInstance | 関連機能 | SQL Serverインスタンスへの接続確立 |

## 画面種別

CLIコマンド（PowerShell関数）

## URL/ルーティング

PowerShellコマンドレット：
- `Get-DbaCustomError`
- `New-DbaCustomError`
- `Remove-DbaCustomError`
- `Copy-DbaCustomError`

## 入出力項目

### Get-DbaCustomError パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQL Serverインスタンス |
| SqlCredential | PSCredential | No | SQL Server認証用資格情報 |
| EnableException | switch | No | 例外処理モードの切り替え |

### New-DbaCustomError パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQL Serverインスタンス |
| SqlCredential | PSCredential | No | SQL Server認証用資格情報 |
| MessageID | int32 | Yes | メッセージID（50001〜2147483647） |
| Severity | int32 | Yes | 重大度レベル（1〜25） |
| MessageText | string | Yes | エラーメッセージテキスト（最大255文字） |
| Language | string | No | 言語名（デフォルト: English） |
| WithLog | switch | No | イベントログへの記録を有効化 |
| EnableException | switch | No | 例外処理モードの切り替え |

### Remove-DbaCustomError パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQL Serverインスタンス |
| SqlCredential | PSCredential | No | SQL Server認証用資格情報 |
| MessageID | int32 | Yes | 削除するメッセージID |
| Language | string | No | 削除する言語（デフォルト: English、Allで全言語） |
| EnableException | switch | No | 例外処理モードの切り替え |

### Copy-DbaCustomError パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| Source | DbaInstanceParameter | Yes | コピー元SQL Serverインスタンス |
| SourceSqlCredential | PSCredential | No | コピー元認証用資格情報 |
| Destination | DbaInstanceParameter[] | Yes | コピー先SQL Serverインスタンス |
| DestinationSqlCredential | PSCredential | No | コピー先認証用資格情報 |
| CustomError | object[] | No | コピーするメッセージID（指定時のみ） |
| ExcludeCustomError | object[] | No | 除外するメッセージID |
| Force | switch | No | 既存メッセージを上書き |
| EnableException | switch | No | 例外処理モードの切り替え |

## 表示項目

### Get-DbaCustomError 出力

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | コンピュータ名 |
| InstanceName | string | インスタンス名 |
| SqlInstance | string | 完全インスタンス名 |
| ID | int | メッセージID |
| Text | string | エラーメッセージテキスト |
| LanguageID | int | 言語ID（数値） |
| Language | string | 言語名 |

### New-DbaCustomError 出力

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ID | int | 作成されたメッセージID |
| Language | string | 言語名 |
| Severity | int | 重大度レベル |
| Text | string | エラーメッセージテキスト |
| IsLogged | bool | イベントログ記録有無 |

### Copy-DbaCustomError 出力

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DateTime | DbaDateTime | 処理日時 |
| SourceServer | string | コピー元サーバー |
| DestinationServer | string | コピー先サーバー |
| Name | string | メッセージID |
| Type | string | オブジェクト種別（Custom error） |
| Status | string | 処理結果（Successful/Skipped/Failed） |
| Notes | string | 補足情報 |

## イベント仕様

### 1-Get（取得）処理

カスタムエラーを取得する処理フロー：

1. Connect-DbaInstanceでSQL Serverに接続
2. $server.UserDefinedMessagesコレクションを走査
3. 各メッセージにComputerName/InstanceName/SqlInstanceを付加
4. Select-DefaultViewで整形して出力

### 2-New（作成）処理

カスタムエラーを作成する処理フロー：

1. Connect-DbaInstance（-AzureUnsupported）でSQL Serverに接続
2. sys.syslanguagesから言語情報を取得・検証
3. New-Object UserDefinedMessageでオブジェクト作成
4. プロパティ設定（ID, Language, Severity, Text, IsLogged）
5. Create()メソッドでSQL Serverに保存
6. UserDefinedMessagesコレクションから作成されたオブジェクトを返却

### 3-Remove（削除）処理

カスタムエラーを削除する処理フロー：

1. Connect-DbaInstance（-AzureUnsupported）でSQL Serverに接続
2. Language指定時は言語情報を検証
3. sp_dropmessageを実行：
   - Language='All'の場合：全言語バージョンを削除
   - 英語の場合：他言語が存在すれば全削除、なければ英語のみ削除
   - その他言語：指定言語のみ削除
4. UserDefinedMessagesコレクションをRefresh

### 4-Copy（コピー）処理

カスタムエラーをインスタンス間でコピーする処理フロー：

1. ソース/デスティネーションに接続（MinimumVersion 9）
2. ソースのカスタムエラーを取得（英語を先に処理）
3. 各メッセージに対して：
   - フィルタ条件（CustomError/ExcludeCustomError）を評価
   - デスティネーションに存在チェック
   - Force指定時は既存を削除
   - Script()でT-SQLを取得し実行
4. 結果オブジェクトを返却

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Get-DbaCustomError | sys.messages | SELECT | カスタムエラーの読み取り |
| New-DbaCustomError | sys.messages | INSERT | カスタムエラーの追加（sp_addmessage経由） |
| Remove-DbaCustomError | sys.messages | DELETE | カスタムエラーの削除（sp_dropmessage経由） |
| Copy-DbaCustomError | sys.messages | INSERT | カスタムエラーのコピー（Script()経由） |

### テーブル別更新項目詳細

#### sys.messages（システムカタログ）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | message_id | MessageIDパラメータ | 50001〜2147483647 |
| INSERT | language_id | Languageから取得 | sys.syslanguages参照 |
| INSERT | severity | Severityパラメータ | 1〜25 |
| INSERT | is_event_logged | WithLogスイッチ | bool値 |
| INSERT | text | MessageTextパラメータ | 最大255文字 |
| DELETE | - | message_id + language_id | sp_dropmessage経由 |

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 発生条件 |
|------|-------------|---------------|---------|
| Error | - | $instance does not have the $Language installed | 指定言語が存在しない場合 |
| Error | - | Error occurred while trying to create a message with id $MessageID | 作成失敗時 |
| Error | - | Error occurred while trying to remove message $MessageID | 削除失敗時 |
| Verbose | - | Creating new server message with id $MessageID | 作成処理開始時 |
| Verbose | - | Removing server message with id $MessageID | 削除処理開始時 |
| Verbose | - | Copying custom error $customErrorId $language | コピー処理時 |
| Verbose | - | Custom error $customErrorId $language exists at destination | コピー先に既存時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 接続エラー | Stop-Functionで処理中断、ConnectionErrorカテゴリ |
| Azure SQL Database | AzureUnsupportedで非対応、エラー表示 |
| 言語未インストール | Stop-Functionで処理継続（Continue） |
| 作成失敗 | Stop-Functionでエラー表示、Continue処理 |
| 削除失敗 | Stop-Functionでエラー表示、Continue処理 |
| コピー失敗 | Statusに"Failed"を設定、Notes記録 |

## 備考

- メッセージIDは50001〜2147483647の範囲で指定
- 重大度は1〜25の範囲で指定（11-16が一般的なユーザーエラー）
- 非英語メッセージを追加するには、先に同じ重大度の英語版が必要
- 英語版を削除すると、全言語バージョンが自動的に削除される
- Azure SQL Databaseは非対応
- WhatIf/Confirmサポートあり（New/Remove/Copy）

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

カスタムエラー操作で使用されるSMOオブジェクト構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaCustomError.ps1 | `public/Get-DbaCustomError.ps1` | UserDefinedMessage出力型の構造 |
| 1-2 | New-DbaCustomError.ps1 | `public/New-DbaCustomError.ps1` | UserDefinedMessageオブジェクトの生成方法 |

**読解のコツ**: SMOのUserDefinedMessageクラスはID, Language, Severity, Text, IsLoggedプロパティを持つ。

#### Step 2: 取得処理を理解する

シンプルなGet処理の実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaCustomError.ps1 | `public/Get-DbaCustomError.ps1` | 76-91行目の処理フロー |

**主要処理フロー**:
1. **79行目**: Connect-DbaInstanceで接続
2. **84行目**: $server.UserDefinedMessagesを走査
3. **85-87行目**: Add-Memberでプロパティ追加
4. **89行目**: Select-DefaultViewで出力整形

#### Step 3: 作成処理を理解する

New処理と言語検証ロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaCustomError.ps1 | `public/New-DbaCustomError.ps1` | 130-179行目の処理フロー |

**主要処理フロー**:
- **133行目**: AzureUnsupportedで接続（Azure非対応）
- **138行目**: sys.syslanguagesから言語情報取得
- **153-168行目**: UserDefinedMessageオブジェクトの生成と設定
- **170行目**: Create()でSQL Serverに保存

#### Step 4: 削除処理の言語依存ロジックを理解する

sp_dropmessageの呼び出しパターンを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Remove-DbaCustomError.ps1 | `public/Remove-DbaCustomError.ps1` | 119-143行目のsp_dropmessage分岐 |

**主要処理フロー**:
- **120-121行目**: Language='All'の場合、全言語削除
- **126-134行目**: 英語の場合、他言語存在チェックして分岐
- **136-138行目**: その他言語の場合、その言語のみ削除

### プログラム呼び出し階層図

```
Get-DbaCustomError
    |
    +-- Connect-DbaInstance
    |
    +-- $server.UserDefinedMessages（SMOコレクション）
    |
    +-- Select-DefaultView（出力整形）

New-DbaCustomError
    |
    +-- Connect-DbaInstance (-AzureUnsupported)
    |
    +-- sys.syslanguagesクエリ（言語検証）
    |
    +-- New-Object UserDefinedMessage
    |
    +-- UserDefinedMessage.Create()

Remove-DbaCustomError
    |
    +-- Connect-DbaInstance (-AzureUnsupported)
    |
    +-- sys.syslanguagesクエリ（言語検証）
    |
    +-- sp_dropmessage（条件分岐あり）
    |
    +-- UserDefinedMessages.Refresh()

Copy-DbaCustomError
    |
    +-- Connect-DbaInstance (Source/Destination)
    |
    +-- $sourceServer.UserDefinedMessages
    |
    +-- UserDefinedMessage.Script()
    |
    +-- $destServer.Query($sql)
```

### データフロー図

```
[入力]                      [処理]                           [出力]

【Get処理】
SQL Server -------> UserDefinedMessages -------> Add-Member -------> 出力オブジェクト
(sys.messages)      SMOコレクション取得         プロパティ追加       (UserDefinedMessage)

【New処理】
パラメータ -------> UserDefinedMessage -------> Create() -------> UserDefinedMessage
(ID/Severity/Text)  オブジェクト生成           SQL Server保存       オブジェクト

【Remove処理】
MessageID/Lang -------> sp_dropmessage -------> Refresh() -------> (なし)
パラメータ              システムストアド         コレクション更新

【Copy処理】
Source Server -------> Script() -------> Query() -------> PSCustomObject
UserDefinedMessages   T-SQL生成        Dest実行         結果オブジェクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaCustomError.ps1 | `public/Get-DbaCustomError.ps1` | ソース | カスタムエラー取得機能 |
| New-DbaCustomError.ps1 | `public/New-DbaCustomError.ps1` | ソース | カスタムエラー作成機能 |
| Remove-DbaCustomError.ps1 | `public/Remove-DbaCustomError.ps1` | ソース | カスタムエラー削除機能 |
| Copy-DbaCustomError.ps1 | `public/Copy-DbaCustomError.ps1` | ソース | カスタムエラーコピー機能 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続確立（依存） |
