# 画面設計書 15-sp_ineachdb実行画面

## 概要

本ドキュメントは、SQL Server First Responder Kitのsp_ineachdbストアドプロシージャが提供する実行画面の設計書です。sp_ineachdbは、複数のデータベースに対して同一のコマンドを実行するユーティリティで、sp_MSforeachdbの改良版として設計されています。

### 本画面の処理概要

sp_ineachdb実行画面は、フィルタリング条件に基づいて対象データベースを選択し、指定されたT-SQLコマンドを各データベースのコンテキストで順次実行するユーティリティです。システムデータベース・ユーザーデータベースの区別、復旧モデル、互換性レベル、状態などの条件でフィルタリングできます。

**業務上の目的・背景**：SQL Serverの標準プロシージャsp_MSforeachdbは、非公開でサポートされていない機能であり、特定の状況でデータベースをスキップするバグが知られています。sp_ineachdbは、これらの問題を解決し、より柔軟なフィルタリングオプションを提供する代替ソリューションです。DBAは、インデックス再構築、統計更新、権限付与、監査設定など、全データベースに対する一括操作を安全かつ確実に実行できます。

**画面へのアクセス方法**：SQL Server Management Studio（SSMS）またはAzure Data Studio等のクエリツールから、以下のようにストアドプロシージャを実行します。
- 基本実行: `EXEC sp_ineachdb @command = 'SELECT DB_NAME(), COUNT(*) FROM sys.tables;';`
- ユーザーDBのみ: `EXEC sp_ineachdb @command = 'DBCC CHECKDB(?) WITH NO_INFOMSGS;', @user_only = 1;`
- 名前パターン: `EXEC sp_ineachdb @command = 'BACKUP LOG ? TO DISK = ''...''', @name_pattern = 'Prod%';`

**主要な操作・処理内容**：
1. @database_listと@exclude_listのパース（カンマ区切り、括弧付き対応）
2. sys.databasesから対象データベース一覧を#ineachdbに取得
3. フィルタリング条件による除外処理
4. 可用性グループ（AG）のセカンダリレプリカ考慮
5. カーソルによる各データベースへのコマンド実行
6. エラーハンドリングと継続実行

**画面遷移**：
- 他のFirst Responder Kitプロシージャからの内部呼び出し
- DBA作業の自動化スクリプトからの実行
- メンテナンスジョブからの定期実行

**権限による表示制御**：
- 対象データベースへのアクセス権限が必要
- 実行するコマンドに応じた権限が必要
- HAS_DBACCESS関数でアクセス可否を判定

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | sp_ineachdb | 主機能 | 複数データベースへのコマンド一括実行 |
| - | sp_MSforeachdb | 代替対象 | 標準の非公開プロシージャ（sp_ineachdbで代替） |

## 画面種別

ユーティリティ / コマンド実行

## URL/ルーティング

T-SQLストアドプロシージャとして実行
```sql
EXEC dbo.sp_ineachdb @command = N'[実行するコマンド]', [@パラメータ名] = [値];
```

## 入出力項目

### 入力パラメータ

| パラメータ名 | データ型 | デフォルト値 | 説明 |
|-------------|---------|-------------|------|
| @command | NVARCHAR(MAX) | NULL | 実行するT-SQLコマンド |
| @replace_character | NCHAR(1) | N'?' | データベース名に置換する文字 |
| @print_dbname | BIT | 0 | 実行前にDB名をPRINT |
| @select_dbname | BIT | 0 | 実行前にDB名をSELECT |
| @print_command | BIT | 0 | 実行前にコマンドをPRINT |
| @print_command_only | BIT | 0 | コマンドのPRINTのみ（実行しない） |
| @suppress_quotename | BIT | 0 | QUOTENAMEを抑制（注意して使用） |
| @system_only | BIT | 0 | システムDBのみ対象 |
| @user_only | BIT | 0 | ユーザーDBのみ対象 |
| @name_pattern | NVARCHAR(300) | N'%' | DB名のLIKEパターン |
| @database_list | NVARCHAR(MAX) | NULL | 対象DBのカンマ区切りリスト |
| @exclude_pattern | NVARCHAR(300) | NULL | 除外するDB名のLIKEパターン |
| @exclude_list | NVARCHAR(MAX) | NULL | 除外DBのカンマ区切りリスト |
| @recovery_model_desc | NVARCHAR(120) | NULL | 復旧モデル（FULL/SIMPLE/BULK_LOGGED） |
| @compatibility_level | TINYINT | NULL | 互換性レベル |
| @state_desc | NVARCHAR(120) | N'ONLINE' | データベース状態 |
| @is_read_only | BIT | 0 | 読み取り専用フラグ |
| @is_auto_close_on | BIT | NULL | AUTO_CLOSEフラグ |
| @is_auto_shrink_on | BIT | NULL | AUTO_SHRINKフラグ |
| @is_broker_enabled | BIT | NULL | Service Brokerフラグ |
| @user_access | NVARCHAR(128) | NULL | ユーザーアクセス（SINGLE_USER/MULTI_USER/RESTRICTED_USER） |
| @Help | BIT | 0 | ヘルプ表示 |
| @is_ag_writeable_copy | BIT | 0 | AG書き込み可能コピーのみ対象 |
| @is_query_store_on | BIT | NULL | Query Store有効フラグ |

## 表示項目

### 結果セット: コマンド実行結果

@commandで指定されたコマンドの結果がそのまま出力されます。

### @select_dbname = 1 の場合

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| ineachdb current database | SYSNAME | 現在処理中のデータベース名 |

### @print_dbname = 1 または @print_command = 1 の場合

PRINTステートメントによるメッセージ出力。

## イベント仕様

### 1-プロシージャ実行

ユーザーがsp_ineachdbを実行すると、以下の処理が順次実行されます。

1. バージョンチェック（@VersionCheckMode=1時は即リターン）
2. @Help=1の場合はヘルプテキストを表示して終了
3. #ineachdb一時テーブル作成
4. @database_listと@exclude_listのパース（再帰CTE使用）
5. sys.databasesから対象データベースをINSERT
6. フィルタリング条件による行削除
7. AG環境でのセカンダリレプリカ考慮
8. 対象DBがなければエラーメッセージ出力
9. カーソルオープン
10. 各データベースでコマンド実行（ループ）
11. カーソルクローズ

### 2-データベースリストパース

@database_listと@exclude_listは以下の形式に対応：
- カンマ区切り: `DB1,DB2,DB3`
- 括弧付き: `[My Database],[Another DB]`
- エスケープ: `[DB with ]] in name]`

### 3-フィルタリング処理

以下の順序でフィルタリングが適用されます：

1. @database_list指定 → 指定されたDBのみ残す
2. @exclude_list指定 → 指定されたDBを除外
3. @system_only / @user_only → システム/ユーザーDB絞り込み
4. @name_pattern → 名前パターンマッチ
5. @exclude_pattern → 名前パターン除外
6. @recovery_model_desc等 → 各種プロパティでフィルタ
7. @user_access → ユーザーアクセス状態
8. @state_desc → データベース状態
9. HAS_DBACCESS → アクセス可否
10. AGセカンダリで接続不可のDB除外

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| コマンド実行 | @commandで指定 | 可変 | 実行するコマンドに依存 |

### 内部一時テーブル

| テーブル名 | 用途 |
|-----------|------|
| #ineachdb | 対象データベース一覧 |

## メッセージ仕様

| メッセージ種別 | メッセージ | 発生条件 |
|--------------|----------|---------|
| エラー | No databases to process. | フィルタリング後に対象DBがない |
| エラー | Could not run against %s : %s. | コマンド実行時のエラー |
| 情報 | /* [DB名] */ | @print_dbname=1時 |
| 情報 | /* For [DB名]: */ + コマンド | @print_command=1時 |

## 例外処理

| 状態 | 説明 | 対応 |
|------|------|------|
| 対象DBなし | フィルタリング後に対象がない | RAISERROR後RETURN |
| コマンドエラー | 個別DBでのエラー | RAISERRORでエラーメッセージ出力後、次のDBへ継続 |

## 備考

- sp_MSforeachdbの代替として設計
- システムDB（master, model, msdb, tempdb）はdatabase_id 1-4
- distributor DBはis_distributor = 1で識別
- SQL Server 2012以降で可用性グループ対応
- SQL Server 2016以降でQuery Store対応
- バージョン: 8.29（2026年2月3日時点）

### @replace_character使用例

```sql
-- デフォルト（?）
EXEC sp_ineachdb @command = 'SELECT ''?'' AS DatabaseName';

-- カスタム文字
EXEC sp_ineachdb @command = 'SELECT ''#'' AS DatabaseName', @replace_character = '#';
```

---

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

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

### 推奨読解順序

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

sp_ineachdbは一時テーブルを使用して対象データベースを管理します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行111: #ineachdbテーブル定義（id, name, is_distributor） |

**読解のコツ**: #ineachdbはsys.databasesからのdatabase_id、name、is_distributorを保持するシンプルな構造です。

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

プロシージャのパラメータと初期化処理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行7-33: プロシージャのパラメータ定義（23パラメータ） |
| 2-2 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行40: バージョン情報 '8.29', '20260203' |
| 2-3 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行47-97: @Help=1時のヘルプ出力 |

**主要処理フロー**:
1. **行40**: バージョン情報設定
2. **行42-45**: VersionCheckModeの場合は即RETURN
3. **行99-108**: ローカル変数宣言

#### Step 3: データベースリストパースを理解する

@database_listと@exclude_listの解析処理です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行165-216: 再帰CTEによるリストパース |

**主要処理フロー**:
- **行165-171**: CTE C の初期化（InリストとOutリストを処理）
- **行172-197**: 再帰部分（カンマと括弧の検出）
- **行198-206**: CTE F でスペース除去と最終名前取得
- **行207-215**: sys.databasesとの結合でINSERT

#### Step 4: フィルタリング処理を理解する

各種条件による行削除処理です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行217-237: 基本フィルタリング |
| 4-2 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行239-254: Query Storeフィルタ（SQL 2016+） |
| 4-3 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行256-261: ユーザーアクセスフィルタ |
| 4-4 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行263-281: 状態・アクセス可否フィルタ |
| 4-5 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行283-315: AG環境でのセカンダリレプリカ除外 |

**主要処理フロー**:
- **行219-220**: @system_only/@user_onlyによる絞り込み
- **行221-222**: @name_pattern/@exclude_patternによるLIKE条件
- **行223-237**: EXISTS句で各種プロパティ条件
- **行285-298**: dm_hadr_database_replica_statesとの結合でAG除外

#### Step 5: コマンド実行を理解する

カーソルによるループ実行処理です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行317-322: 対象なしチェック |
| 5-2 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行324-331: カーソル宣言・オープン |
| 5-3 | sp_ineachdb.sql | `sp_ineachdb.sql` | 行336-373: ループ処理 |

**主要処理フロー**:
- **行325-327**: カーソル宣言（LOCAL FAST_FORWARD）
- **行338**: @suppress_quotename考慮
- **行339**: @replace_characterの置換
- **行341-361**: @print_dbname/@select_dbname/@print_command処理
- **行357-361**: @print_command_only=0の場合のみ実行
- **行359-360**: sp_executesqlでコマンド実行
- **行364-367**: エラーハンドリング

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

```
sp_ineachdb
    |
    +-- #ineachdb一時テーブル作成
    |
    +-- CTE C, F（再帰CTEによるリストパース）
    |      |
    |      +-- @database_list処理
    |      +-- @exclude_list処理
    |
    +-- sys.databases
    |      |
    |      +-- #ineachdbへINSERT
    |
    +-- フィルタリング（DELETE FROM #ineachdb）
    |      |
    |      +-- @system_only / @user_only
    |      +-- @name_pattern / @exclude_pattern
    |      +-- 各種プロパティ条件
    |      +-- @user_access
    |      +-- @state_desc / HAS_DBACCESS
    |      +-- AG secondary除外
    |
    +-- カーソル処理
           |
           +-- WHILE @@FETCH_STATUS <> -1
                  |
                  +-- @print_dbname → PRINT
                  +-- @select_dbname → SELECT
                  +-- @print_command → PRINT
                  +-- sp_executesql（@print_command_only=0時）
                  +-- TRY/CATCH エラーハンドリング
```

### データフロー図

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

@database_list          ───▶  再帰CTEパース
@exclude_list                      |
                                   ▼
sys.databases           ───▶  #ineachdbへINSERT
                                   |
                                   ▼
@system_only            ───▶  フィルタリング
@user_only                  DELETE FROM #ineachdb
@name_pattern                      |
@exclude_pattern                   ▼
@recovery_model_desc
@compatibility_level    ───▶  プロパティフィルタ
@state_desc                        |
@is_read_only                      ▼

@is_ag_writeable_copy   ───▶  AG環境フィルタ
                                   |
                                   ▼
                            対象DBなしチェック      ───▶  エラーメッセージ
                                   |
                                   ▼
@command                ───▶  カーソルループ
@replace_character              |
                                ▼
                            各DBで実行
                                |
@print_dbname           ───▶  PRINT /* DB名 */
@select_dbname          ───▶  SELECT DB名
@print_command          ───▶  PRINT コマンド
                                |
                                ▼
@print_command_only=0   ───▶  sp_executesql        ───▶  コマンド結果
                                |
                                ▼
                            TRY/CATCH              ───▶  エラーメッセージ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sp_ineachdb.sql | `sp_ineachdb.sql` | ソース | メインストアドプロシージャ |
