# 機能設計書 220-Set-DbaDbOwner

## 概要

本ドキュメントは、データベースの所有者を指定されたログインに変更するSet-DbaDbOwner関数の機能設計書です。

### 本機能の処理概要

Set-DbaDbOwnerは、現在の所有権がターゲットと一致しない場合にデータベースの所有権を変更します。これは、他の環境からのデータベース復元後に孤立した所有者や一貫性のない所有権が発生した場合に、インスタンス全体でデータベースを所有する人を標準化するのに特に役立ちます。

**業務上の目的・背景**：データベースの所有者は、セキュリティおよび管理上の理由で重要です。異なる環境からデータベースを復元すると、所有者が孤立したり不適切になったりすることがあります。本機能は、複数のデータベースに対して一貫した所有権パターンを維持し、ベストプラクティスに準拠した所有者設定を効率的に行います。

**機能の利用シーン**：
- データベース復元後に所有者を標準化する場合
- 複数データベースの所有者を一括変更する場合
- セキュリティ監査で所有者の不整合を修正する場合
- 退職者のアカウントから所有権を移管する場合

**主要な処理内容**：
1. 対象データベースの取得
2. ターゲットログインの検証（存在確認、グループ除外、マッピングユーザー除外）
3. データベース状態の確認（Normal、更新可能）
4. 所有者の変更とAlter()実行
5. 結果の出力

**関連システム・外部連携**：
- SQL Server Management Objects (SMO)
- SQL Serverセキュリティシステム（ログイン、データベースユーザー）

**権限による制御**：データベースに対するALTER AUTHORIZATION権限、またはdb_ownerロールのメンバーシップが必要です。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIインターフェース | 主画面 | コマンドライン実行 |

## 機能種別

構成変更 / セキュリティ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No | 対象SQL Serverインスタンス | パイプライン入力可 |
| SqlCredential | PSCredential | No | 認証用資格情報 | PSCredential型 |
| Database | object[] | No | 対象データベース名 | ワイルドカード対応 |
| ExcludeDatabase | object[] | No | 除外するデータベース名 | ワイルドカード対応 |
| InputObject | Database[] | No | パイプライン入力 | SMO Databaseオブジェクト |
| TargetLogin | string | No | 新しい所有者ログイン | デフォルト: sa（またはリネームされたsysadmin） |
| EnableException | switch | No | 例外を有効化 | スイッチ型 |
| WhatIf | switch | No | 実行シミュレーション | スイッチ型 |
| Confirm | switch | No | 確認プロンプト | スイッチ型 |

### 入力データソース

- SqlInstance指定によるデータベース取得
- Get-DbaDatabase等からのパイプライン入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverホストコンピューター名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なインスタンス名 |
| Database | string | データベース名 |
| Owner | string | 新しい所有者ログイン名 |

### 出力先

- パイプライン出力（PSCustomObject）
- 所有者が既にターゲットと一致している場合は出力なし

## 処理フロー

### 処理シーケンス

```
1. 入力検証
   └─ SqlInstance/InputObjectのいずれかを確認

2. データベース取得
   └─ Get-DbaDatabase（SqlInstance指定時）

3. 各データベースの処理
   ├─ システムデータベース除外
   ├─ アクセス可能性確認
   └─ ターゲットログイン決定

4. ログイン検証
   ├─ ログイン存在確認
   ├─ Windowsグループ除外
   └─ マッピングユーザー除外

5. 所有者変更
   ├─ 状態チェック（Normal、更新可能）
   └─ SetOwner()、Alter()実行

6. 結果出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SqlInstance or InputObject?}
    B -->|Neither| C[エラー終了]
    B -->|SqlInstance| D[Get-DbaDatabase]
    B -->|InputObject| E[InputObjectを使用]

    D --> E
    E --> F[各DBをループ]

    F --> G{システムDB?}
    G -->|Yes| H[スキップ]
    G -->|No| I{Accessible?}

    I -->|No| J[警告、スキップ]
    I -->|Yes| K{TargetLogin指定?}

    K -->|No| L[ID=1のログイン取得（sa）]
    K -->|Yes| M[指定ログインを使用]

    L --> N{ログイン存在?}
    M --> N
    N -->|No| O[エラー、次へ継続]
    N -->|Yes| P{Windowsグループ?}

    P -->|Yes| Q[エラー、次へ継続]
    P -->|No| R{ShouldProcess確認}

    R -->|No| H
    R -->|Yes| S{DB状態=Normal?}

    S -->|No| T[警告、スキップ]
    S -->|Yes| U{更新可能?}

    U -->|No| V[警告、スキップ]
    U -->|Yes| W{マッピングユーザー?}

    W -->|Yes| X[警告、スキップ]
    W -->|No| Y[SetOwner実行]

    Y --> Z[Alter実行]
    Z --> AA[PSCustomObject出力]

    AA --> AB{次のDB?}
    H --> AB
    J --> AB
    O --> AB
    Q --> AB
    T --> AB
    V --> AB
    X --> AB
    AB -->|Yes| F
    AB -->|No| AC[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 入力必須 | SqlInstanceまたはInputObjectのいずれかが必須 | 常時 |
| BR-002 | デフォルト所有者 | TargetLogin未指定時はID=1のログイン（通常sa）を使用 | TargetLogin未指定 |
| BR-003 | システムDB除外 | システムデータベースは処理対象外 | 常時 |
| BR-004 | グループ除外 | Windowsグループは所有者に設定不可 | 常時 |
| BR-005 | マッピングユーザー除外 | DB内にマッピング済みのログインは所有者に設定不可 | 常時 |
| BR-006 | 状態制約 | Normal状態かつ更新可能なDBのみ処理 | 常時 |

### 計算ロジック

```powershell
# デフォルトのsa取得（リネームされていても対応）
$TargetLogin = ($server.logins | Where-Object { $_.id -eq 1 }).Name
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 所有者変更 | sys.databases | UPDATE | 所有者（owner_sid）の更新 |

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

SMO SetOwner()メソッドを使用。内部的にALTER AUTHORIZATION ON DATABASE::が実行されます。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 入力不足 | SqlInstance/InputObject両方未指定 | エラーメッセージ出力、処理終了 |
| - | ログイン未存在 | 指定ログインがインスタンスに存在しない | 警告、次のDBへ継続 |
| - | Windowsグループ | ターゲットがWindowsグループ | 警告、次のDBへ継続 |
| - | 状態異常 | DB状態がNormalでない | 警告、スキップ |
| - | 更新不可 | DBが読み取り専用 | 警告、スキップ |
| - | マッピング済み | ターゲットがDB内ユーザーとしてマッピング済み | 警告、スキップ |
| - | 更新失敗 | SetOwner/Alter実行失敗 | Stop-Functionで継続 |

### リトライ仕様

リトライは行いません。エラー発生時は次のデータベースへ継続処理します。

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

SMOのSetOwner()/Alter()メソッド内でトランザクション管理されます。

## パフォーマンス要件

特になし。所有者変更は軽量なメタデータ操作です。

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

- ALTER AUTHORIZATION権限が必要
- 所有者変更はデータベース内の権限継承に影響する可能性あり
- sa（またはsysadmin）以外を所有者にする場合は慎重に検討

## 備考

- ベストプラクティス参照: http://weblogs.sqlteam.com/dang/archive/2008/01/13/Database-Owner-Troubles.aspx
- saアカウントがリネームされている環境でも自動検出
- 所有者変更前にdb.Ownerプロパティを読み込み（SMOの既知の問題対応 #8528）

---

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

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

### 推奨読解順序

#### Step 1: パラメータ定義を理解する

関数のパラメータ構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Set-DbaDbOwner.ps1 | `public/Set-DbaDbOwner.ps1` 95-107行目 | パラメータ定義、エイリアス |

**読解のコツ**: TargetLoginにはエイリアス"Login"があり、互換性のために維持されています。

#### Step 2: 入力検証とデータベース取得を理解する

対象データベースの取得ロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Set-DbaDbOwner.ps1 | `public/Set-DbaDbOwner.ps1` 109-127行目 | 入力検証、DB取得、フィルタリング |

**主要処理フロー**:
1. **110-113行目**: SqlInstance/InputObject両方未指定時のエラー
2. **115-117行目**: Get-DbaDatabase呼び出し
3. **121-123行目**: システムDB除外
4. **124-127行目**: アクセス可能性チェック

#### Step 3: ログイン検証処理を理解する

ターゲットログインの検証ロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Set-DbaDbOwner.ps1 | `public/Set-DbaDbOwner.ps1` 132-146行目 | デフォルトsa取得、存在確認、グループ除外 |

**主要処理フロー**:
- **133-135行目**: TargetLogin未指定時にID=1のログイン（sa）を取得
- **138-140行目**: ログイン存在確認
- **143-146行目**: Windowsグループ除外

#### Step 4: 所有者変更処理を理解する

実際の所有者変更と出力を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Set-DbaDbOwner.ps1 | `public/Set-DbaDbOwner.ps1` 148-182行目 | 状態チェック、SetOwner、出力 |

**主要処理フロー**:
- **155-157行目**: DB状態チェック（Normal）
- **159-161行目**: 更新可能性チェック
- **163-165行目**: マッピングユーザー除外
- **167-168行目**: db.Ownerプロパティ読み込み（SMO問題対応）
- **168行目**: SetOwner()実行
- **170行目**: Alter()実行
- **171-177行目**: PSCustomObject出力

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

```
Set-DbaDbOwner
    │
    ├─ Get-DbaDatabase (DB取得)
    │      └─ Connect-DbaInstance
    │
    ├─ Server.Logins (ログイン検証)
    │
    ├─ Database.Users (マッピングユーザー確認)
    │
    ├─ Database.SetOwner() (所有者設定)
    │
    ├─ Database.Alter() (変更適用)
    │
    └─ Stop-Function (エラー処理)
```

### データフロー図

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

SqlInstance        ───▶ Get-DbaDatabase       ───▶
     or                       │
InputObject                   ▼
     +             ───▶ ログイン検証          ───▶
TargetLogin                   │
                              ▼
               ───▶ 状態チェック           ───▶
                              │
                              ▼
               ───▶ SetOwner/Alter         ───▶ PSCustomObject
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Set-DbaDbOwner.ps1 | `public/Set-DbaDbOwner.ps1` | ソース | メイン関数 |
| Get-DbaDatabase.ps1 | `public/Get-DbaDatabase.ps1` | ソース | データベース取得 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続 |
| Stop-Function.ps1 | `private/functions/Stop-Function.ps1` | ソース | エラー処理 |
