# 機能設計書 81-Dismount-DbaDatabase

## 概要

本ドキュメントは、dbatools PowerShellモジュールのDismount-DbaDatabase関数の機能設計を定義する。この関数は、SQL Serverインスタンスからデータベースを安全にデタッチ（切り離し）するための機能を提供する。

### 本機能の処理概要

Dismount-DbaDatabase は、SQL Server インスタンスからデータベースをデタッチするコマンドレットである。デタッチ前に複数の安全性チェックを実行し、ミラーリングや可用性グループなどの高可用性構成も適切に処理できる。

**業務上の目的・背景**：データベースの移行作業において、バックアップ/リストア方式ではなくファイルコピー方式でデータベースを移動する場合、デタッチ操作が必要となる。また、データベースのアーカイブ、ストレージの再配置、サーバーのデコミッションなど、様々なシナリオでデータベースのデタッチが求められる。本機能は、システムデータベースの保護、レプリケーション状態の確認、スナップショットの存在チェックなど、デタッチ失敗を防ぐための包括的な検証を自動的に実行する。

**機能の利用シーン**：
- データベースファイルを別サーバーに物理的に移動する際の事前準備
- 使用しなくなったデータベースをオフラインアーカイブとして保管する場合
- ストレージの再構成やディスク移行時のデータベース再配置
- テスト環境でのデータベースのクリーンアップ
- 可用性グループやミラーリング構成からのデータベース削除と同時デタッチ

**主要な処理内容**：
1. 対象SQL Serverインスタンスへの接続確立
2. システムデータベースチェック（master, model, msdb, tempdbはデタッチ不可）
3. レプリケーション状態の確認（レプリケートされているデータベースはスキップ）
4. データベーススナップショットの存在確認（スナップショットが存在する場合はスキップ）
5. ミラーリング状態の確認（-Forceオプションでミラー解除可能）
6. 可用性グループメンバーシップの確認（-Forceオプションでグループから削除可能）
7. アクティブ接続の確認と強制終了（-Forceオプション使用時）
8. 統計情報の更新（-UpdateStatisticsオプション使用時）
9. データベースのデタッチ実行

**関連システム・外部連携**：
- SQL Server Management Objects (SMO) を使用したデータベース操作
- 可用性グループ（AlwaysOn AG）との連携
- データベースミラーリングとの連携
- 接続中のクライアントセッション管理

**権限による制御**：
- SQL Server上でデータベースをデタッチするには、db_owner固定データベースロールまたはsysadmin固定サーバーロールのメンバーシップが必要
- 可用性グループからの削除や、ミラーリングの解除には追加の権限が必要な場合がある

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 18 | データベース管理 | 補助機能 | データベースのデタッチ |

## 機能種別

データベース操作 / デタッチ処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | Yes (SqlInstanceパラメータセット) | 対象SQL Serverインスタンス | 接続可能なSQL Serverインスタンス名 |
| SqlCredential | PSCredential | No | 代替認証資格情報 | 有効なPSCredentialオブジェクト |
| Database | string[] | Yes (SqlInstanceパラメータセット) | デタッチするデータベース名。ワイルドカード対応 | 存在するデータベース名 |
| InputObject | Microsoft.SqlServer.Management.Smo.Database[] | Yes (Pipelineパラメータセット) | パイプライン経由のデータベースオブジェクト | SMO Databaseオブジェクト |
| UpdateStatistics | switch | No | デタッチ前に統計情報を更新 | - |
| Force | switch | No | ミラー解除、AG削除、接続終了を強制実行 | - |
| WhatIf | switch | No | 実行内容のプレビュー表示 | - |
| Confirm | switch | No | 実行前の確認プロンプト | - |
| EnableException | switch | No | 例外処理の有効化 | - |

### 入力データソース

- パイプライン入力: Get-DbaDatabase の出力を直接受け取り可能
- 直接指定: SqlInstance と Database パラメータでインスタンスとデータベース名を指定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverが動作するコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なSQL Serverインスタンス名（コンピュータ\インスタンス形式） |
| Database | string | デタッチされたデータベース名 |
| DatabaseID | int | デタッチされたデータベースの一意識別子 |
| DetachResult | string | デタッチ操作の結果（"Success"） |

### 出力先

- PowerShellパイプライン: PSCustomObjectとして出力
- コンソール出力: 結果オブジェクトのテーブル形式表示

## 処理フロー

### 処理シーケンス

```
1. パラメータ検証とForce設定の適用
   └─ Forceが指定された場合、ConfirmPreferenceを'none'に設定

2. SqlInstanceの処理ループ
   └─ 各インスタンスへの接続確立（Connect-DbaInstance）
   └─ データベースオブジェクトの取得（$server.Databases）

3. データベースごとの処理ループ
   ├─ データベースの最新状態を取得（Refresh()）
   ├─ システムデータベースチェック
   ├─ レプリケーション状態チェック
   ├─ スナップショット存在チェック
   ├─ ミラーリング状態チェック（Force時は解除）
   ├─ 可用性グループチェック（Force時は削除）
   ├─ アクティブ接続チェック（Force時は終了）
   └─ デタッチ実行（server.DetachDatabase()）

4. 結果オブジェクトの出力
   └─ PSCustomObject形式で成功情報を出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[インスタンスへ接続]
    B --> C{接続成功?}
    C -->|No| D[エラー出力して次へ]
    C -->|Yes| E[データベースオブジェクト取得]
    E --> F{システムDB?}
    F -->|Yes| G[スキップ]
    F -->|No| H{レプリケート?}
    H -->|Yes| G
    H -->|No| I{スナップショット?}
    I -->|Yes| G
    I -->|No| J{ミラーリング?}
    J -->|Yes| K{Force?}
    K -->|No| G
    K -->|Yes| L[ミラー解除]
    J -->|No| M{AG参加?}
    L --> M
    M -->|Yes| N{Force?}
    N -->|No| G
    N -->|Yes| O[AGから削除]
    M -->|No| P{接続あり?}
    O --> P
    P -->|Yes| Q{Force?}
    Q -->|No| G
    Q -->|Yes| R[接続終了]
    P -->|No| S[デタッチ実行]
    R --> S
    S --> T[結果出力]
    G --> U[次のDB]
    T --> U
    D --> U
    U --> V{残りDBあり?}
    V -->|Yes| F
    V -->|No| W[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | システムデータベース保護 | master, model, msdb, tempdbはデタッチ不可 | 常時 |
| BR-002 | レプリケーション保護 | レプリケートされているデータベースはデタッチ不可 | ReplicationOptions != "None" |
| BR-003 | スナップショット保護 | スナップショットが存在するデータベースはデタッチ不可 | スナップショットの親DBの場合 |
| BR-004 | ミラーリング強制解除 | ミラーリング中のDBはForceオプションで解除後デタッチ | IsMirroringEnabled且つForce |
| BR-005 | AG強制削除 | AG参加中のDBはForceオプションでAGから削除後デタッチ | AvailabilityGroupName存在且つForce |
| BR-006 | 接続強制終了 | アクティブ接続はForceオプションで強制終了 | 接続存在且つForce |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| デタッチ | sys.databases | DELETE（論理的） | データベースをSQL Serverから切り離し |

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

#### sys.databases

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | name, state, is_in_standby | デタッチ対象の確認 | SMO経由 |
| 論理削除 | - | sys.databasesからエントリを削除 | DetachDatabase メソッド |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | SQL Serverに接続できない | インスタンス名・認証情報を確認 |
| SystemDatabaseError | 業務エラー | システムデータベースをデタッチしようとした | 対象から除外する |
| ReplicationError | 業務エラー | レプリケートされたデータベース | レプリケーションを先に解除 |
| SnapshotError | 業務エラー | スナップショットが存在する | スナップショットを先に削除 |
| MirroringError | 業務エラー | ミラーリング中（Forceなし） | -Forceを使用するかミラーを解除 |
| AGError | 業務エラー | AG参加中（Forceなし） | -Forceを使用するかAGから削除 |
| ConnectionError | 業務エラー | アクティブ接続あり（Forceなし） | -Forceを使用するか接続を終了 |

### リトライ仕様

自動リトライは実装されていない。エラー発生時はStop-Functionで処理を停止し、次のデータベースの処理に移行する。

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

デタッチ操作自体はSQL Server内部でトランザクション管理される。Force オプション使用時のミラー解除、AG削除、接続終了は個別の操作として実行され、途中で失敗した場合は以降の操作は実行されない。

## パフォーマンス要件

- UpdateStatistics オプション使用時は統計更新の時間が追加される
- 大量の接続が存在する場合、Force オプションでの接続終了に時間がかかる場合がある

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

- SqlCredential パラメータで代替認証資格情報を安全に渡すことが可能
- デタッチ操作にはdb_ownerまたはsysadmin権限が必要
- Force オプションは強力な権限を必要とするため、使用には注意が必要

## 備考

- Detach-DbaDatabase はエイリアスとして使用可能
- デタッチ後のデータベースファイル（.mdf, .ldf）はディスク上に残る
- 再度使用するにはMount-DbaDatabase（Attach）を使用する

---

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

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

### 推奨読解順序

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

出力されるPSCustomObjectの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Dismount-DbaDatabase.ps1 | `public/Dismount-DbaDatabase.ps1` | 212-219行目で出力オブジェクトの構造を確認 |

**読解のコツ**: PowerShellのPSCustomObjectは、@{}ハッシュテーブルをキャストして作成される。プロパティ名と値のペアで構成される。

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

コマンドの入口となるパラメータ定義と初期処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Dismount-DbaDatabase.ps1 | `public/Dismount-DbaDatabase.ps1` | 86-98行目のparam()ブロックでパラメータセット構造を理解 |

**主要処理フロー**:
1. **86-98行目**: パラメータセット定義。SqlInstanceセットとPipelineセットの2つが存在
2. **99-101行目**: begin ブロックでForce時のConfirmPreference設定

#### Step 3: 接続処理を理解する

SQL Serverへの接続確立ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Dismount-DbaDatabase.ps1 | `public/Dismount-DbaDatabase.ps1` | 103-119行目の接続とデータベースオブジェクト取得 |

**主要処理フロー**:
- **104-108行目**: Connect-DbaInstanceで接続確立。失敗時はStop-FunctionでContinue
- **110-114行目**: Databaseパラメータ指定時のフィルタリング

#### Step 4: 検証ロジックを理解する

デタッチ前の各種安全性チェックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Dismount-DbaDatabase.ps1 | `public/Dismount-DbaDatabase.ps1` | 121-158行目の各種検証処理 |

**主要処理フロー**:
- **125-127行目**: システムデータベースチェック（IsSystemObject）
- **129-132行目**: レプリケーション状態チェック（ReplicationOptions）
- **135-140行目**: スナップショット存在チェック（Get-DbaDbSnapshot使用）
- **142-145行目**: ミラーリング状態チェック（IsMirroringEnabled）
- **147-152行目**: 可用性グループチェック（AvailabilityGroupName）
- **154-158行目**: アクティブ接続チェック（Get-DbaProcess使用）

#### Step 5: Force処理を理解する

強制オプション使用時の解除・削除・終了処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Dismount-DbaDatabase.ps1 | `public/Dismount-DbaDatabase.ps1` | 160-205行目のForce処理 |

**主要処理フロー**:
- **162-166行目**: アクティブ接続の強制終了（Stop-DbaProcess）
- **168-178行目**: ミラーリングの解除（ChangeMirroringState）
- **181-196行目**: 可用性グループからの削除（AvailabilityDatabases.Drop）
- **198-204行目**: 残存接続の再終了

#### Step 6: デタッチ実行を理解する

最終的なデタッチ処理と結果出力を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | Dismount-DbaDatabase.ps1 | `public/Dismount-DbaDatabase.ps1` | 207-224行目のデタッチ実行 |

**主要処理フロー**:
- **209行目**: データベースIDの保存（デタッチ後は取得不可のため）
- **210行目**: SMOのDetachDatabaseメソッド呼び出し
- **212-219行目**: 成功時の結果オブジェクト出力

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

```
Dismount-DbaDatabase
    │
    ├─ Connect-DbaInstance
    │      └─ SQL Server接続の確立
    │
    ├─ Get-DbaDbSnapshot
    │      └─ スナップショット一覧の取得
    │
    ├─ Get-DbaProcess
    │      └─ アクティブ接続の取得
    │
    ├─ Stop-DbaProcess
    │      └─ 接続の強制終了
    │
    ├─ $db.ChangeMirroringState()
    │      └─ ミラーリングの解除（SMO）
    │
    ├─ $server.AvailabilityGroups[].AvailabilityDatabases[].Drop()
    │      └─ AGからのDB削除（SMO）
    │
    └─ $server.DetachDatabase()
           └─ デタッチ実行（SMO）
```

### データフロー図

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

SqlInstance ───┬──▶ Connect-DbaInstance
               │           │
Database ──────┤           ▼
               │    Databases取得
               │           │
InputObject ───┘           ▼
                    検証チェック群
                    (System/Repl/Snap/Mirror/AG/Conn)
                           │
                           ▼
                   ┌───────┴───────┐
                   │     Force?    │
                   └───────┬───────┘
                           │
                   Yes ────┼──── No
                     │     │      │
              ┌──────┘     │      └──────▶ Stop-Function
              │            │
        解除/削除処理      │
              │            │
              └─────▶ DetachDatabase()
                           │
                           ▼
                    PSCustomObject ──────▶ パイプライン出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Dismount-DbaDatabase.ps1 | `public/Dismount-DbaDatabase.ps1` | ソース | メイン関数定義 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続ユーティリティ |
| Get-DbaDbSnapshot.ps1 | `public/Get-DbaDbSnapshot.ps1` | ソース | スナップショット情報取得 |
| Get-DbaProcess.ps1 | `public/Get-DbaProcess.ps1` | ソース | 接続プロセス取得 |
| Stop-DbaProcess.ps1 | `public/Stop-DbaProcess.ps1` | ソース | プロセス強制終了 |
| Stop-Function.ps1 | `private/functions/Stop-Function.ps1` | ソース | エラーハンドリング関数 |
| Write-Message.ps1 | `private/functions/Write-Message.ps1` | ソース | メッセージ出力関数 |
