# 機能設計書 202-Remove-DbaCustomError

## 概要

本ドキュメントは、dbatools PowerShellモジュールのRemove-DbaCustomError関数の機能設計を定義する。この関数は、SQL Serverのsys.messagesシステムカタログからユーザー定義エラーメッセージを削除するための機能を提供する。

### 本機能の処理概要

Remove-DbaCustomErrorは、アプリケーションがSQL Serverに登録したカスタムエラーメッセージをsys.messagesカタログから削除する機能である。メッセージIDは50001から2147483647の範囲内のユーザー定義メッセージを対象とする。

**業務上の目的・背景**：アプリケーションのデコミッション（廃止）、テスト環境のクリーンアップ、またはアプリケーションデプロイメント中のカスタムエラーメッセージライフサイクル管理において、不要になったユーザー定義メッセージを削除する必要がある。この関数はそのような運用シナリオで使用される。

**機能の利用シーン**：
- アプリケーション廃止時に関連するカスタムエラーメッセージをクリーンアップする場合
- テスト環境でテスト用に作成したエラーメッセージを削除する場合
- アプリケーションバージョンアップ時に古いエラーメッセージを削除して新しいものに置き換える場合
- 複数言語版のエラーメッセージを一括削除する場合

**主要な処理内容**：
1. SQL Serverインスタンスへの接続を確立
2. 言語パラメータの検証（sys.syslanguagesから言語情報を取得）
3. sp_dropmessageストアドプロシージャを使用してエラーメッセージを削除
4. "All"指定時は全言語版のメッセージを一括削除
5. 英語版削除時は他言語版の存在を確認し、必要に応じて全言語版を削除
6. UserDefinedMessagesコレクションをリフレッシュ

**関連システム・外部連携**：
- SQL Server sys.messages：ユーザー定義エラーメッセージのカタログ
- SQL Server sys.syslanguages：言語情報の参照
- sp_dropmessage：メッセージ削除用システムストアドプロシージャ
- New-DbaCustomError：エラーメッセージ作成の対となるコマンド

**権限による制御**：sysadminまたはserveradmin固定サーバーロールのメンバーシップが必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 223 | カスタムエラー | 主画面 | カスタムエラーの削除 |

## 機能種別

データ削除（DDL操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象のSQL Serverインスタンス。複数指定可能 | パイプライン入力対応 |
| SqlCredential | PSCredential | No | 代替認証情報。Windows認証、SQL認証、AD認証対応 | - |
| MessageID | int32 | No | 削除するカスタムエラーメッセージID | 50001から2147483647の範囲 |
| Language | String | No | 削除する言語バージョン。デフォルトは'English' | 'All'または有効な言語名/エイリアス |
| EnableException | switch | No | 例外を直接スローするかどうか | - |

### 入力データソース

- パラメータ入力：SqlInstance、MessageID、Language
- パイプライン入力：SqlInstanceパラメータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| なし | - | このコマンドはパイプラインに出力を返さない |

### 出力先

- SQL Server sys.messages：メッセージが削除される
- 画面表示：Verboseメッセージとして処理状況を表示

## 処理フロー

### 処理シーケンス

```
1. SqlInstanceごとにループ処理開始
   └─ 1.1 Connect-DbaInstanceでSQL Serverに接続
       └─ 接続失敗時はStop-FunctionでContinue
2. Language検証（"All"以外の場合）
   └─ 2.1 sys.syslanguagesから言語情報を取得
   └─ 2.2 言語が存在しない場合はStop-FunctionでContinue
   └─ 2.3 言語名、エイリアス、言語IDを取得
3. ShouldProcess確認
4. メッセージ削除処理
   └─ 4.1 Language="All"の場合
       └─ sp_dropmessage @lang = 'all'を実行
   └─ 4.2 英語版（us_english）の場合
       └─ 他言語版の存在を確認
       └─ 他言語版がある場合は全言語版を削除
       └─ 英語版のみの場合は英語版のみ削除
   └─ 4.3 他言語版の場合
       └─ 指定言語版のみを削除
5. UserDefinedMessagesコレクションをリフレッシュ
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SqlInstanceループ}
    B -->|次のインスタンス| C[Connect-DbaInstance]
    C --> D{接続成功?}
    D -->|No| E[Stop-Function]
    E --> B
    D -->|Yes| F{Language = 'All'?}
    F -->|No| G[言語情報を取得]
    G --> H{言語存在?}
    H -->|No| I[Stop-Function]
    I --> B
    H -->|Yes| J{ShouldProcess?}
    F -->|Yes| J
    J -->|No| B
    J -->|Yes| K{Language判定}
    K -->|All| L[sp_dropmessage @lang='all']
    K -->|us_english| M{他言語版存在?}
    M -->|Yes| L
    M -->|No| N[sp_dropmessage 英語版のみ]
    K -->|Other| O[sp_dropmessage 指定言語]
    L --> P[UserDefinedMessages.Refresh]
    N --> P
    O --> P
    P --> B
    B -->|完了| Q[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-202-01 | メッセージID範囲制限 | MessageIDは50001から2147483647の範囲内でなければならない | 常時 |
| BR-202-02 | 英語版削除順序 | 英語版（us_english）を削除する際、他言語版が存在する場合は全言語版を自動的に削除する | Language指定時 |
| BR-202-03 | 言語存在確認 | 指定された言語がsys.syslanguagesに存在しない場合はエラーとする | Language != 'All'時 |
| BR-202-04 | Azure非対応 | Azure SQLではサポートされない（AzureUnsupported指定） | 常時 |

### 計算ロジック

特になし

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 言語情報取得 | sys.syslanguages | SELECT | 言語名、エイリアス、言語IDの取得 |
| 他言語確認 | sys.messages | SELECT | 指定MessageIDの他言語版存在確認 |
| メッセージ削除 | sys.messages | DELETE | sp_dropmessageによるメッセージ削除 |

### テーブル別操作詳細

#### sys.syslanguages

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | name, alias, msglangid | name = Language OR alias = Language | TOP 1で1件のみ取得 |

#### sys.messages

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | COUNT(*) | message_id = MessageID AND language_id <> 1033 | 他言語版の存在確認 |
| DELETE | - | sp_dropmessage経由 | 直接DELETEではなくストアドプロシージャ使用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | SQL Serverへの接続失敗 | 接続情報を確認して再試行 |
| LanguageNotFound | 引数エラー | 指定言語がインストールされていない | 有効な言語名を指定 |
| DropMessageError | 実行エラー | sp_dropmessage実行時のエラー | エラー詳細を確認 |

### リトライ仕様

リトライ処理は実装されていない。

## トランザクション仕様

sp_dropmessageは内部でトランザクション管理を行う。明示的なトランザクション制御は実装されていない。

## パフォーマンス要件

- 単一メッセージ削除は即時完了
- 複数インスタンスへの同時実行時は順次処理

## セキュリティ考慮事項

- sysadminまたはserveradmin権限が必要
- ConfirmImpact=Lowにより、誤操作リスクは低く設定されている
- SqlCredentialによる認証情報の安全な受け渡し

## 備考

- New-DbaCustomErrorとの組み合わせでエラーメッセージの更新が可能（例示あり）
- Adam Lancaster (github.com/lancasteradam) により作成
- SQL Server 2021以降では動作確認が必要

---

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

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

### 推奨読解順序

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

SQL Serverのメッセージカタログの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sys.messages | SQL Server システムビュー | message_id, language_id, severity, text の構造 |
| 1-2 | sys.syslanguages | SQL Server システムビュー | 言語情報（name, alias, msglangid） |

**読解のコツ**: SQL Serverでは言語ID 1033が英語（us_english）を表す。他言語版を削除する前に英語版を削除することはできないというSQL Serverの制約がある。

#### Step 2: エントリーポイントを理解する

Remove-DbaCustomError.ps1の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Remove-DbaCustomError.ps1 | `public/Remove-DbaCustomError.ps1` | 関数全体の処理フロー |

**主要処理フロー**:
1. **94-100行目**: インスタンス接続処理
2. **102-112行目**: 言語検証処理
3. **119-139行目**: sp_dropmessage呼び出しロジック（条件分岐）
4. **145行目**: UserDefinedMessagesコレクションのリフレッシュ

#### Step 3: 関連機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaCustomError.ps1 | `public/New-DbaCustomError.ps1` | エラーメッセージ作成の対となる機能 |
| 3-2 | Get-DbaCustomError.ps1 | `public/Get-DbaCustomError.ps1` | エラーメッセージ取得機能 |

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

```
Remove-DbaCustomError
    │
    ├─ Connect-DbaInstance
    │      └─ SQL Server接続確立
    │
    ├─ $server.Query()
    │      ├─ 言語情報取得クエリ
    │      ├─ 他言語版存在確認クエリ
    │      └─ sp_dropmessage実行
    │
    ├─ Stop-Function
    │      └─ エラー処理
    │
    └─ $server.UserDefinedMessages.Refresh()
           └─ SMOコレクション更新
```

### データフロー図

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

SqlInstance ─────────▶ Connect-DbaInstance
    │                        │
    │                        ▼
MessageID ───────────▶ パラメータ検証
    │                        │
    │                        ▼
Language ────────────▶ sys.syslanguages照会 ──────▶ エラー
    │                        │                    (言語不存在時)
    │                        ▼
    │                  ShouldProcess確認
    │                        │
    │                        ▼
    └────────────────▶ sp_dropmessage実行
                             │
                             ▼
                    sys.messages ────────────────▶ メッセージ削除
                             │
                             ▼
                    UserDefinedMessages.Refresh()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Remove-DbaCustomError.ps1 | `public/Remove-DbaCustomError.ps1` | ソース | メイン関数実装 |
| New-DbaCustomError.ps1 | `public/New-DbaCustomError.ps1` | ソース | カスタムエラー作成（対となる機能） |
| Get-DbaCustomError.ps1 | `public/Get-DbaCustomError.ps1` | ソース | カスタムエラー取得 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | インスタンス接続 |
