# バッチ設計書 10-sp_ineachdb

## 概要

本ドキュメントは、SQL Server First Responder Kitに含まれるsp_ineachdbストアドプロシージャのバッチ設計書です。sp_ineachdbは指定されたコマンドを複数のデータベースに対して実行するユーティリティツールです。

### 本バッチの処理概要

sp_ineachdbは、SQL Serverの標準機能であるsp_MSforeachdbの代替として設計された、より柔軟で信頼性の高いストアドプロシージャです。指定されたT-SQLコマンドを、フィルタ条件に合致する複数のデータベースに対して順次実行します。

**業務上の目的・背景**：DBA業務では、全データベースまたは特定条件のデータベース群に対して同一のコマンドを実行する必要が頻繁に発生します。例えば、全データベースのサイズ確認、インデックス再構築、統計情報更新、権限設定などです。sp_MSforeachdbは機能が限定的で、エラーハンドリングやフィルタリング機能が不十分でした。sp_ineachdbはこれらの課題を解決し、より安全で柔軟なマルチデータベース操作を可能にします。

**バッチの実行タイミング**：データベース管理作業が必要な際に随時実行。定期メンテナンス、監査、レポート作成時に使用されます。

**主要な処理内容**：
1. 対象データベースリストの構築
2. フィルタ条件による絞り込み
3. 各データベースに対するコマンド実行
4. エラーハンドリングと継続処理

**前後の処理との関連**：単独で使用可能です。他のFirst Responder Kitツールと組み合わせて、全データベースに対する診断を実行することもできます。

**影響範囲**：渡されたコマンドに依存します。コマンド内容によっては各データベースの状態を変更する可能性があります。

## バッチ種別

ユーティリティ・管理

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 手動 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| SQL Serverバージョン | SQL Server 2008以降（Microsoft-supported versions） |
| 必要権限 | 各データベースへのアクセス権限、実行コマンドに必要な権限 |
| 依存オブジェクト | sys.databases、sys.dm_hadr_* (AG環境) |

### 実行可否判定

- 対象データベースが1つ以上存在すること
- 指定されたコマンドが有効なT-SQLであること

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| @command | NVARCHAR(MAX) | No | NULL | 実行するT-SQLコマンド |
| @replace_character | NCHAR(1) | No | N'?' | DB名に置換する文字 |
| @print_dbname | BIT | No | 0 | DB名をPRINT出力 |
| @select_dbname | BIT | No | 0 | DB名をSELECT出力 |
| @print_command | BIT | No | 0 | コマンドをPRINT出力 |
| @print_command_only | BIT | No | 0 | コマンド出力のみ（実行しない） |
| @suppress_quotename | BIT | No | 0 | QUOTENAME抑制（注意が必要） |
| @system_only | BIT | No | 0 | システムDBのみ |
| @user_only | BIT | No | 0 | ユーザーDBのみ |
| @name_pattern | NVARCHAR(300) | No | N'%' | DB名パターン（LIKE） |
| @database_list | NVARCHAR(MAX) | No | NULL | 対象DBリスト（カンマ区切り） |
| @exclude_pattern | NVARCHAR(300) | No | NULL | 除外パターン（LIKE） |
| @exclude_list | NVARCHAR(MAX) | No | NULL | 除外DBリスト（カンマ区切り） |
| @recovery_model_desc | NVARCHAR(120) | No | NULL | 復旧モデルフィルタ |
| @compatibility_level | TINYINT | No | NULL | 互換性レベルフィルタ |
| @state_desc | NVARCHAR(120) | No | N'ONLINE' | 状態フィルタ |
| @is_read_only | BIT | No | 0 | 読み取り専用フィルタ |
| @is_auto_close_on | BIT | No | NULL | AUTO_CLOSEフィルタ |
| @is_auto_shrink_on | BIT | No | NULL | AUTO_SHRINKフィルタ |
| @is_broker_enabled | BIT | No | NULL | Service Brokerフィルタ |
| @user_access | NVARCHAR(128) | No | NULL | ユーザーアクセスモード |
| @Help | BIT | No | 0 | ヘルプ表示 |
| @Version | VARCHAR(30) | No | NULL | バージョン（OUTPUT） |
| @VersionDate | DATETIME | No | NULL | バージョン日付（OUTPUT） |
| @VersionCheckMode | BIT | No | 0 | バージョンチェックモード |
| @is_ag_writeable_copy | BIT | No | 0 | AG書き込み可能コピーのみ |
| @is_query_store_on | BIT | No | NULL | Query Storeフィルタ |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| sys.databases | システムカタログ | データベース一覧 |
| sys.dm_hadr_database_replica_states | DMV | AGレプリカ状態 |
| sys.availability_replicas | システムカタログ | AGレプリカ情報 |
| sys.dm_hadr_availability_group_states | DMV | AG状態 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| メッセージ | PRINT | DB名、コマンド出力 |
| 結果セット | TABLE | @select_dbname=1時のDB名 |
| コマンド結果 | 可変 | 実行コマンドの出力 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | 該当なし |
| 出力先 | メッセージウィンドウ |
| 文字コード | - |
| 区切り文字 | - |

## 処理フロー

### 処理シーケンス

```
1. パラメータ検証
   └─ @Help、@VersionCheckModeチェック
2. 対象データベース構築
   └─ @database_list、@exclude_listパース
3. フィルタ適用
   └─ @system_only、@user_only、@name_pattern等
4. 状態フィルタ
   └─ ONLINE、アクセス可能チェック
5. AGフィルタ（SQL 2012以降）
   └─ secondary_role_allow_connections、@is_ag_writeable_copy
6. カーソルループ
   └─ 各DBに対してコマンド実行
7. エラーハンドリング
   └─ TRY-CATCHで継続処理
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{@Help=1?}
    B -->|Yes| C[ヘルプ表示]
    C --> D[終了]
    B -->|No| E[#ineachdbテーブル作成]
    E --> F[database_list/exclude_listパース]
    F --> G[sys.databasesから挿入]
    G --> H[system_only/user_onlyフィルタ]
    H --> I[name_pattern/exclude_patternフィルタ]
    I --> J[recovery_model等フィルタ]
    J --> K{SQL >= 2016?}
    K -->|Yes| L[query_storeフィルタ]
    K -->|No| M[user_accessフィルタ]
    L --> M
    M --> N[state_desc/アクセス可能フィルタ]
    N --> O{SQL >= 2012?}
    O -->|Yes| P[AGセカンダリフィルタ]
    O -->|No| Q{対象DB存在?}
    P --> Q
    Q -->|No| R[エラー:No databases]
    Q -->|Yes| S[カーソルオープン]
    S --> T[FETCH NEXT]
    T --> U{EOF?}
    U -->|No| V[コマンド置換・実行]
    V --> W{エラー?}
    W -->|Yes| X[RAISERROR継続]
    W -->|No| Y[次へ]
    X --> Y
    Y --> T
    U -->|Yes| Z[カーソルクローズ]
    Z --> D
    R --> D
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| データベース一覧取得 | sys.databases | SELECT | 対象DB特定 |
| AG状態取得 | sys.dm_hadr_* | SELECT | AGフィルタ |
| コマンド実行 | 指定コマンド依存 | 可変 | ユーザー指定コマンド |

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

#### #ineachdb（一時テーブル）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| CREATE | id, name, is_distributor | - | 対象DBリスト |
| INSERT | database_id, name, is_distributor | sys.databasesから | フィルタ後 |
| DELETE | - | 各種フィルタ条件 | 条件不合致削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 情報 | 対象DBが0件 | フィルタ条件を緩和 |
| - | 警告 | 個別DB実行エラー | エラーメッセージを確認、処理は継続 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

### 障害時対応

- 個別DBでエラーが発生しても、他のDBに対する処理は継続
- RAISERRORで警告（Severity 1）を出力

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | コマンド依存 |
| コミットタイミング | コマンド依存 |
| ロールバック条件 | コマンド依存 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 対象DB数 |
| 目標処理時間 | コマンド内容依存 |
| メモリ使用量上限 | 環境依存 |

## 排他制御

- コマンド内容に依存
- 各DBのコンテキストで実行されるため、DBごとのロックが適用される

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| DB名出力 | @print_dbname=1時 | '/* [DBName] */' |
| コマンド出力 | @print_command=1時 | '/* For [DBName]: */' + コマンド |
| エラー出力 | コマンド失敗時 | 'Could not run against [DBName] : [Error]' |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 該当なし | - | - |

## 備考

- バージョン: 8.29（2026年2月3日）
- ライセンス: MIT License
- 依存関係: なし（単独実行可能）
- 特記事項:
  - sp_MSforeachdbの代替として設計
  - @replace_character（デフォルト'?'）をDB名に置換
  - @print_command_only=1でドライラン可能
  - @suppress_quotename=1はセキュリティ上注意が必要
  - AG環境でsecondary_role_allow_connections=0のDBは自動スキップ
  - @is_ag_writeable_copy=1でAGのプライマリコピーのみ対象
  - Query Store対応（SQL Server 2016以降）
  - カンマ区切りリストで角括弧[]内のDB名も正しくパース

