# 通知設計書 38-StopAt日時無効

## 概要

本ドキュメントは、sp_DatabaseRestoreストアドプロシージャにおいて、@StopAtパラメータの値が有効な日時として認識されない場合に発生するエラー通知の設計を記述する。

### 本通知の処理概要

この通知は、データベース復元操作において、ポイントインタイムリカバリ用の@StopAtパラメータに指定された値が、形式は正しい（14桁の数字）が、実在しない日時である場合にユーザーに警告を発するためのエラーメッセージである。

**業務上の目的・背景**：ポイントインタイムリカバリは、特定の時点までデータベースを復元する重要な機能である。@StopAtパラメータには実在する日時を指定する必要があり、例えば「20240230」（2月30日は存在しない）や「20241315」（月は01-12のみ有効）のような値は無効である。この事前検証により、ユーザーに早期に問題を通知し、正しい日時でのパラメータ指定を促す。

**通知の送信タイミング**：sp_DatabaseRestoreストアドプロシージャの実行中、ログバックアップ復元フェーズの@StopAtパラメータ検証時に発生する。具体的には、形式チェック（No.37）を通過した後、ISDATEによる日時妥当性チェックで失敗した場合にトリガーされる。

**通知の受信者**：ストアドプロシージャを実行したSQL Serverセッションの呼び出し元ユーザーまたはアプリケーション。RAISERRORによりクライアントに直接メッセージが返され、処理は即座に終了する。

**通知内容の概要**：エラーメッセージとして「@StopAt is not a valid datetime.」が表示され、指定された値が有効な日時ではないことを明示的に伝える。

**期待されるアクション**：ユーザーは@StopAtパラメータの値を確認し、実在する日時（例：20240115103000 = 2024年1月15日10時30分00秒）に修正してから、再度ストアドプロシージャを実行する必要がある。

## 通知種別

SQLエラーメッセージ（RAISERROR - Severity 16, State 1）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（Severity 16） |
| リトライ | 無（処理即時終了） |

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

現在のSQL Serverセッションの呼び出し元に対してRAISERRORでメッセージを送信。WITH NOWAITオプションにより即時送信され、その後RETURNにより処理が終了する。

## 通知テンプレート

### SQLエラーメッセージ

| 項目 | 内容 |
|-----|------|
| メッセージレベル | 16（ユーザーエラー） |
| 状態 | 1 |
| オプション | WITH NOWAIT |

### 本文テンプレート

```
@StopAt is not a valid datetime.
```

### 添付ファイル

なし

## テンプレート変数

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

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ストアドプロシージャ実行 | sp_DatabaseRestoreの呼び出し | ISDATE(変換後の@StopAt) = 0 | StopAtパラメータが有効な日時でない場合にエラーを発生 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| @StopAt IS NULL | パラメータが指定されていない場合はチェックをスキップ |
| 形式チェックでエラー | No.37の形式チェックでエラーの場合はこのチェックに到達しない |
| ISDATE = 1 | 有効な日時の場合は通知しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[sp_DatabaseRestore実行開始] --> B[ログ復元フェーズ]
    B --> C{@StopAt IS NOT NULL?}
    C -->|No| D[StopAtなしで処理続行]
    C -->|Yes| E[形式チェック - No.37]
    E -->|エラー| F[形式エラーで終了]
    E -->|OK| G{ISDATE = 1?}
    G -->|No| H[RAISERROR - 日時無効]
    G -->|Yes| I[処理続行]
    H --> J[RETURN - 処理終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | パラメータ検証のみのため、テーブル参照なし | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | ログ出力のみでテーブル更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 無効な日付 | 存在しない日付（例：2月30日） | 有効な日付に修正 |
| 無効な月 | 13月以上または0月以下 | 01-12の範囲内の月に修正 |
| 無効な時刻 | 24時以上または60分以上 | 有効な時刻に修正 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし、即座に処理終了） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（ストアドプロシージャ実行時に即時送信）

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

- 個人情報の取り扱いなし
- パラメータ値のみを検証するため、機密情報の露出リスクなし

## 備考

- ISDATEによるチェックの前に、@StopAtは日時形式に変換される
- STUFF関数を使用して、14桁の数字を'yyyyMMdd hh:mm:ss'形式に変換
- 変換例：'20240115103000' → '20240115 10:30:00'
- このチェックはNo.37（形式チェック）を通過した後に実行される
- ISDATEはSQL Serverの組み込み関数で、文字列が有効な日時かどうかを判定

---

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

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

### 推奨読解順序

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

@StopAtパラメータの定義と変換ロジックを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | パラメータ@StopAtの定義（行37）を確認 |

**読解のコツ**: NVARCHAR(14)として定義されており、14桁の数字文字列を日時形式に変換して検証する。

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

処理の起点となるファイル・関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | ログ復元フェーズの開始（行1352）を確認 |

**主要処理フロー**:
1. **行1352**: @StopAtがNULLでないかチェック
2. **行1357-1361**: 形式チェック（No.37）
3. **行1363-1367**: 日時妥当性チェック

#### Step 3: 検証ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 行1363-1367でISDATEチェックを確認 |

**主要処理フロー**:
- **行1363**: ISDATE(STUFF(STUFF(STUFF(@StopAt, 13, 0, ':'), 11, 0, ':'), 9, 0, ' ')) = 0
- **行1365**: RAISERROR発生
- **行1366**: RETURN - 処理終了

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

```
sp_DatabaseRestore
    |
    +-- パラメータ検証フェーズ
    |
    +-- フルバックアップ復元フェーズ
    |
    +-- 差分バックアップ復元フェーズ
    |
    +-- ログバックアップ復元フェーズ (行1174-1499)
    |       |
    |       +-- @StopAt検証 (行1352-1367)
    |               |
    |               +-- NULL チェック (行1352)
    |               |
    |               +-- 形式チェック (行1357-1361) - No.37
    |               |
    |               +-- 日時妥当性チェック (行1363-1367) ← 本通知の発生箇所
    |                       |
    |                       +-- STUFF関数で日時形式に変換
    |                       |
    |                       +-- ISDATE関数で妥当性判定
    |
    +-- リカバリ処理
```

### データフロー図

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

@StopAt ───▶ 形式チェック ───▶ STUFF関数変換 ───▶ ISDATE チェック ───▶ RAISERROR
'20240115103000'    (行1357)     '20240115 10:30:00'    (行1363)         (メッセージ)
                                       |
                                       v
                            STUFF(STUFF(STUFF(@StopAt,
                                13, 0, ':'),
                                11, 0, ':'),
                                9, 0, ' ')
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | ソース | データベース復元用ストアドプロシージャ本体 |
