# 通知設計書 89-テーブル書き込み

## 概要

本ドキュメントは、SQL Server First Responder Kitのsp_BlitzCache.sqlにおける「テーブル書き込み」通知の設計を定義する。この通知は、クエリプラン分析結果を永続テーブルに書き込む処理の開始を示す情報メッセージである。

### 本通知の処理概要

この通知は、sp_BlitzCacheストアドプロシージャがクエリプラン分析結果を指定された出力テーブルに書き込む処理の開始を示す。@OutputDatabaseName、@OutputSchemaName、@OutputTableNameパラメータが指定されている場合に、結果を永続テーブルに保存する。

**業務上の目的・背景**：sp_BlitzCacheの分析結果は通常、結果セットとして返される。しかし、定期的な監視や履歴分析のために、結果を永続テーブルに保存する必要がある場合がある。この機能により、SQL Server Agentジョブで定期実行し、パフォーマンストレンドを追跡したり、問題のあるクエリの履歴を保持したりできる。この通知は、テーブルへの書き込み処理が開始されたことをユーザーに通知する。

**通知の送信タイミング**：sp_BlitzCacheプロシージャの実行中、@OutputTableNameが指定されている場合に、OutputResultsToTableラベルにジャンプした直後、実際のテーブル書き込み処理開始前のタイミングで送信される。

**通知の受信者**：この通知はRAISERROR関数によりSQL Server Management Studio（SSMS）のメッセージウィンドウ、またはsqlcmdなどのコマンドラインツールの標準出力に表示される。主な受信者は、sp_BlitzCacheを実行しているDBA、データベース開発者、システム管理者である。

**通知内容の概要**：「Writing results to table.」という英語メッセージが表示され、分析結果のテーブル書き込み処理が開始されたことを示す。

**期待されるアクション**：通知の受信者は、テーブル書き込み処理が進行していることを確認し、処理完了を待つ。書き込み先テーブルが存在しない場合は自動作成されるため、特別なアクションは不要である。

## 通知種別

コンソール出力（RAISERROR WITH NOWAIT）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（WITH NOWAITオプションにより即座に出力） |
| 優先度 | 低（情報レベル、重大度0） |
| リトライ | なし（単発の情報メッセージ） |

### 送信先決定ロジック

sp_BlitzCacheを実行しているセッションのクライアント接続に対して直接出力される。送信先の動的な決定ロジックは存在せず、実行元のセッションに対して常に通知される。

## 通知テンプレート

### メール通知の場合

該当なし（コンソール出力のみ）

### 本文テンプレート

```
Writing results to table.
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | 固定メッセージのため変数なし | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プロシージャ実行 | sp_BlitzCache内のテーブル書き込み処理開始 | @OutputTableNameが指定されている | 出力テーブルが指定された場合のみ通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| @OutputTableName未指定 | 出力テーブルが指定されていない場合は通知されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[分析処理完了] --> B{@OutputTableName指定?}
    B -->|No| I[結果セット返却のみ]
    B -->|Yes| C[GOTO OutputResultsToTable]
    C --> D[RAISERROR実行]
    D --> E[メッセージ即時出力]
    E --> F{出力先サーバー指定?}
    F -->|Yes| G[リンクサーバー経由書き込み]
    F -->|No| H[ローカルDB書き込み]
    G --> J[テーブル存在チェック]
    H --> J
    J --> K{テーブル存在?}
    K -->|No| L[CREATE TABLE]
    K -->|Yes| M[既存テーブル使用]
    L --> N[INSERT INTO]
    M --> N
    N --> O[書き込み完了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| ##BlitzCacheProcs | プランキャッシュ分析結果の読み取り | グローバル一時テーブル |
| sys.servers | リンクサーバーの存在確認 | 出力サーバー指定時 |
| sys.databases | 出力データベースの存在確認 | ローカル/リモート |
| INFORMATION_SCHEMA.TABLES | 出力テーブルの存在確認 | 出力先データベース |
| INFORMATION_SCHEMA.SCHEMATA | 出力スキーマの存在確認 | 出力先データベース |

### テーブル別参照項目詳細

#### ##BlitzCacheProcs

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| 全カラム | 出力テーブルへのINSERT | WHERE SPID = @@SPID |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| @OutputSchemaName.@OutputTableName | CREATE/INSERT | 分析結果の永続化 |

#### 出力テーブル（動的に指定）

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | ServerName | @@SERVERNAME | サーバー名 |
| INSERT | CheckDate | SYSDATETIMEOFFSET() | チェック日時 |
| INSERT | Version | @Version | sp_BlitzCacheバージョン |
| INSERT | 他多数のカラム | ##BlitzCacheProcsの値 | 分析結果全体 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 出力サーバー不存在 | 指定されたリンクサーバーが存在しない | RAISERROR(重大度16)でエラー通知 |
| 出力データベース不存在 | 指定されたデータベースが存在しない | RAISERROR(重大度16)でエラー通知 |
| スキーマ名無効 | 指定されたスキーマが存在しない | エラーメッセージを出力 |
| テーブル作成失敗 | 権限不足等 | エラーメッセージを出力 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（sp_BlitzCache実行時に即座に出力）

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

- 通知内容に機密情報は含まれない
- 出力テーブルへの書き込みにはINSERT権限、テーブル作成にはCREATE TABLE権限が必要
- リンクサーバー経由の場合、リンクサーバーの権限設定に依存
- VIEW SERVER STATE権限が必要（sp_BlitzCache実行の前提条件）

## 備考

- この通知はsp_BlitzCacheの出力機能の一部であり、@OutputTableNameが指定された場合にのみ表示される
- WITH NOWAITオプションにより、バッファリングなしで即座にクライアントに送信される
- 重大度0は情報メッセージを意味し、エラーではない
- 出力テーブルが存在しない場合は、適切なスキーマで自動作成される
- リンクサーバー（@OutputServerName）が指定された場合は、リモートサーバーに書き込む
- 出力テーブルにはAI関連カラム（ai_prompt、ai_advice、ai_payload、ai_raw_response）も含まれる

---

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

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

### 推奨読解順序

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

まず、出力テーブルのスキーマ定義を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sp_BlitzCache.sql | `sp_BlitzCache.sql` | @OutputDatabaseName、@OutputSchemaName、@OutputTableNameパラメータの定義を確認 |
| 1-2 | sp_BlitzCache.sql | `sp_BlitzCache.sql` | 出力テーブルのCREATE TABLE文でカラム定義を確認 |

**読解のコツ**: CREATE TABLE文は動的SQLで構築され、多数のカラムが定義される。AI関連カラムは後から追加された比較的新しい機能である。

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

処理の起点となるラベルジャンプを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sp_BlitzCache.sql | `sp_BlitzCache.sql` | OutputResultsToTableラベルとGOTO文の使用箇所を確認 |

**主要処理フロー**:
1. **行7601**: OutputResultsToTable:ラベル定義
2. **行7603**: RAISERROR('Writing results to table.', 0, 1) WITH NOWAITでメッセージ出力
3. **行7605-7608**: 出力先名のQUOTENAME処理
4. **行7616-7663**: 出力先の検証処理

#### Step 3: テーブル作成・書き込み処理を理解する

実際のテーブル作成と書き込みロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sp_BlitzCache.sql | `sp_BlitzCache.sql` | 動的SQLによるCREATE TABLE文の構築 |
| 3-2 | sp_BlitzCache.sql | `sp_BlitzCache.sql` | INSERT INTO文の構築と実行 |

**主要処理フロー**:
- **行7668-7768**: @ValidOutputLocation = 1の場合のCREATE TABLE処理
- **行7686-7768**: 出力テーブルのスキーマ定義（カラム一覧）
- **後続行**: INSERT INTO処理（##BlitzCacheProcsから出力テーブルへ）

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

```
sp_BlitzCache
    |
    +-- [分析処理]
    |
    +-- IF @OutputTableName IS NOT NULL
    |       |
    |       +-- GOTO OutputResultsToTable
    |
    +-- OutputResultsToTable:
            |
            +-- RAISERROR('Writing results to table.')  <-- 本通知
            |
            +-- QUOTENAME(@OutputServerName, ...)
            |
            +-- IF @OutputServerName IS NOT NULL
            |       |
            |       +-- リンクサーバー検証
            |       |
            |       +-- リモートDB存在確認
            |
            +-- ELSE
            |       |
            |       +-- ローカルDB存在確認
            |
            +-- IF @ValidOutputLocation = 1
                    |
                    +-- 動的SQL構築
                    |
                    +-- IF NOT EXISTS (テーブル)
                    |       |
                    |       +-- CREATE TABLE
                    |
                    +-- INSERT INTO @OutputTableName
                            |
                            +-- SELECT FROM ##BlitzCacheProcs
```

### データフロー図

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

@OutputServerName          --> QUOTENAME                        --> クォート処理済み名前
@OutputDatabaseName
@OutputSchemaName
@OutputTableName
         |
         v
sys.servers               --> 存在確認                          --> @ValidOutputServer
sys.databases             --> 存在確認                          --> @ValidOutputLocation
         |
         v
INFORMATION_SCHEMA        --> テーブル存在確認                  --> CREATE/SKIP判定
         |
         v
##BlitzCacheProcs         --> SELECT                            --> @OutputTableName
- ServerName                   INSERT INTO                          - 全分析結果
- CheckDate
- Version
- QueryType
- Warnings
- ai_prompt
- ai_advice
- ...

                           コンソール出力 <-- RAISERROR
                           "Writing results to table."
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sp_BlitzCache.sql | `sp_BlitzCache.sql` | ソース | テーブル書き込み処理を含むメインストアドプロシージャ |
