# 通知設計書 57-統計更新権限不足

## 概要

本ドキュメントは、sp_BlitzLock実行時にテンポラリテーブルの統計更新（UPDATE STATISTICS）を試みた際、db_ownerまたはsysadmin権限がないために失敗した場合に発生する警告通知について定義する。

### 本通知の処理概要

sp_BlitzLockはSQL Serverのデッドロック分析を行うストアドプロシージャであり、パフォーマンス最適化のためにテンポラリテーブル（#t）に対してUPDATE STATISTICSを実行する。Azure SQL Database以外の環境（@RDS = 0）では、大規模なROWCOUNTとPAGECOUNTを設定して統計を更新するが、この操作にはdb_ownerまたはsysadmin権限が必要である。権限不足の場合、SQL Serverは「Cannot find object」（エラー1088）という誤解を招くエラーを返すため、より明確なエラーメッセージに変換してユーザーに通知する。

**業務上の目的・背景**：UPDATE STATISTICS WITH ROWCOUNT/PAGECOUNTは統計情報を操作する高度な機能であり、権限制限がある。エラー1088は本来「オブジェクトが見つからない」を意味するが、権限不足時にも発生する。これは非常に誤解を招くエラーメッセージであるため、sp_BlitzLockは明確な権限エラーメッセージに変換することで、ユーザーが問題を迅速に理解できるようにする。

**通知の送信タイミング**：sp_BlitzLock実行時に、@RDS = 0の環境で#tテーブルに対するUPDATE STATISTICS実行時にエラー1088が発生した場合。

**通知の受信者**：sp_BlitzLockを実行したSQL Serverユーザー（DBA、開発者など）。

**通知内容の概要**：db_ownerまたはsysadmin権限なしでは#tempテーブルに対するUPDATE STATISTICSを実行できないことを通知する。

**期待されるアクション**：ユーザーはdb_ownerまたはsysadmin権限を持つアカウントでsp_BlitzLockを再実行するか、現在のユーザーにdb_owner権限を付与する。または、統計更新をスキップして処理を続行させる（処理は続行される）。

## 通知種別

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

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（RAISERROR WITH NOWAITによる即時出力） |
| 優先度 | 中（警告レベル、重大度0） |
| リトライ | なし |

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

sp_BlitzLockを実行したセッションのメッセージ出力に直接表示される。

## 通知テンプレート

### コンソール出力

| 項目 | 内容 |
|-----|------|
| 出力方法 | RAISERROR WITH NOWAIT（重大度0、状態1） |
| メッセージタイプ | 情報メッセージ |

### 本文テンプレート

```
Cannot run UPDATE STATISTICS on a #temp table without db_owner or sysadmin permissions
```

### 添付ファイル

なし

## テンプレート変数

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

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ストアドプロシージャ実行 | sp_BlitzLock実行 | @RDS = 0 AND ERROR_NUMBER() = 1088（UPDATE STATISTICS実行時） | 非Azure環境で統計更新がエラー1088で失敗した場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| @RDS = 1 | Azure SQL Database環境の場合（UPDATE STATISTICS自体を実行しない） |
| エラーが発生しない | db_ownerまたはsysadmin権限を持っている場合 |
| ERROR_NUMBER() <> 1088 | 別のエラーが発生した場合（THROWで再スロー） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[sp_BlitzLock実行] --> B{@RDS = 0?}
    B -->|No| Z[UPDATE STATISTICSスキップ]
    B -->|Yes| C[BEGIN TRY]
    C --> D[UPDATE STATISTICS #t<br/>WITH ROWCOUNT, PAGECOUNT]
    D --> E{成功?}
    E -->|Yes| F[処理続行]
    E -->|No| G[BEGIN CATCH]
    G --> H{ERROR_NUMBER = 1088?}
    H -->|Yes| I[RAISERROR 警告メッセージ]
    H -->|No| J[THROW 元のエラー]
    I --> K[処理続行（統計更新なし）]
    J --> L[エラー終了]
    F --> M[終了]
    K --> M
    Z --> M
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| #t | 統計更新対象のテンポラリテーブル | デッドロックデータ格納用 |

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

なし

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| #t | UPDATE STATISTICS | 統計情報の更新（ROWCOUNTとPAGECOUNT設定） |

#### #t統計更新

| 操作 | 項目 | 更新値 | 備考 |
|-----|-----|-------|------|
| UPDATE STATISTICS | ROWCOUNT | 9223372036854775807 | BIGINT最大値 |
| UPDATE STATISTICS | PAGECOUNT | 9223372036854775807 | BIGINT最大値 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| エラー1088 | db_owner/sysadmin権限なし | 明確なメッセージで警告、処理続行 |
| その他のエラー | 統計更新時の別エラー | THROWで再スロー |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

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

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

- 本通知には機密情報は含まれない
- 権限要件（db_owner/sysadmin）が明示される
- 警告後も処理は続行されるが、統計情報が最適化されない可能性がある

## 備考

- エラー1088は「Cannot find the object」という誤解を招くメッセージを返す
- このエラーハンドリングにより、ユーザーは真の原因（権限不足）を理解できる
- 統計更新が失敗しても、sp_BlitzLockの主要機能（デッドロック分析）は正常に動作する
- Azure SQL Database（@RDS = 1）ではこの処理自体がスキップされる

---

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

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

### 推奨読解順序

#### Step 1: 統計更新とエラーハンドリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sp_BlitzLock.sql | `sp_BlitzLock.sql` | UPDATE STATISTICSとTRY-CATCHブロック |

**主要処理フロー**:
1. **行920**: @RDS = 0条件のIF文開始
2. **行921**: BEGIN TRY
3. **行923-927**: UPDATE STATISTICS #t WITH ROWCOUNT, PAGECOUNT
4. **行929**: BEGIN CATCH
5. **行930-931**: コメント：誤解を招くエラーについての説明
6. **行932**: ERROR_NUMBER() = 1088のチェック
7. **行934-935**: RAISERROR警告メッセージ
8. **行937-939**: ELSE節でTHROW（他のエラーの場合）

**読解のコツ**: TRY-CATCHでラップされており、エラー1088のみを特別にハンドリングしている。コメントに「Misleading error returned」と説明がある。

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

```
sp_BlitzLock (エントリーポイント)
    │
    ├─ [条件チェック] @RDS = 0?
    │      │
    │      ├─ [No] UPDATE STATISTICSスキップ
    │      │
    │      └─ [Yes]
    │             │
    │             ├─ BEGIN TRY
    │             │      │
    │             │      └─ UPDATE STATISTICS #t
    │             │         WITH ROWCOUNT = 最大値, PAGECOUNT = 最大値
    │             │
    │             └─ BEGIN CATCH
    │                    │
    │                    ├─ [条件チェック] ERROR_NUMBER() = 1088?
    │                    │      │
    │                    │      ├─ [Yes]
    │                    │      │      ├─ SET @d = CONVERT(...)
    │                    │      │      └─ RAISERROR 'Cannot run UPDATE STATISTICS...'
    │                    │      │
    │                    │      └─ [No]
    │                    │             └─ THROW（元のエラーを再スロー）
    │                    │
    │                    └─ END CATCH
    │
    └─ [以降のデッドロック分析処理]
```

### データフロー図

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

@RDS ────────────────────▶ [条件評価]
                              │
                    ┌─────────┴──────────┐
                    │                    │
                    ▼                    ▼
               [@RDS = 0]          [@RDS = 1]
                    │                    │
                    ▼                    ▼
         UPDATE STATISTICS #t        スキップ
                    │
                    ▼
              [TRY-CATCH]
                    │
           ┌────────┴────────┐
           │                 │
           ▼                 ▼
       [成功]           [エラー]
           │                 │
           ▼                 ▼
        続行          ERROR_NUMBER()
                          = 1088?
                    ┌───────┴───────┐
                    │               │
                    ▼               ▼
               [Yes]           [No]
                    │               │
                    ▼               ▼
         RAISERROR警告        THROW
         処理続行            エラー終了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sp_BlitzLock.sql | `sp_BlitzLock.sql` | ソース | 本通知を発生させるメインプロシージャ（行920-941） |
| Install-All-Scripts.sql | `Install-All-Scripts.sql` | ソース | 全スクリプト一括インストール（行29291-29301に同一ロジック） |
| Install-Azure.sql | `Install-Azure.sql` | ソース | Azure向けインストール（行22196-22206に同一ロジック） |
