# 機能設計書 500-New-DbaAgentJobStep

## 概要

本ドキュメントは、SQL Server Agent ジョブステップの作成機能 `New-DbaAgentJobStep` の設計仕様を記載する。

### 本機能の処理概要

既存の SQL Server Agent ジョブに新しいステップを追加する機能である。T-SQL、PowerShell、SSIS パッケージ、OS コマンドなど複数のサブシステムタイプをサポートし、リトライロジック、成功/失敗時の分岐制御、出力キャプチャなどの詳細設定が可能。

**業務上の目的・背景**：SQL Server Agent ジョブは複数のステップで構成されることが多く、各ステップには異なる処理タイプと実行オプションが必要となる。SSMS を使用したステップの手動追加は、複数ジョブへの展開時に非効率であり、設定ミスも発生しやすい。本機能により、PowerShell からジョブステップの一括追加が可能となり、複雑な自動化ワークフローを効率的に構築できる。既存ステップ間への挿入機能も備え、ステップ順序の自動再番号付けを行う。

**機能の利用シーン**：
- ジョブへのステップ追加
- 既存ステップ間への新規ステップ挿入
- 複数インスタンスへのジョブステップ一括展開
- 自動化スクリプトでのジョブ構築
- リトライロジックや分岐制御の設定

**主要な処理内容**：
1. 対象 SQL Server インスタンスへの接続
2. ジョブの存在確認
3. ステップ名/ID の重複チェック（Force/Insert 対応）
4. SMO JobStep オブジェクトの作成と設定
5. ステップの保存と結果出力

**関連システム・外部連携**：SQL Server Agent ジョブシステム、各種サブシステム（T-SQL、PowerShell、CmdExec、SSIS、Replication、Analysis Services）。

**権限による制御**：SQL Server への sysadmin 権限が必要。SQL Server 2000 以上が対象。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | ジョブステップ管理 | 主画面 | SQLエージェントジョブステップの新規作成 |

## 機能種別

データ作成（INSERT）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQLServerインスタンス | 必須、配列対応 |
| SqlCredential | PSCredential | No | 代替認証情報 | - |
| Job | object[] | Yes | 対象ジョブ名または Job オブジェクト | 必須 |
| StepId | int | No | ステップID（実行順序） | - |
| StepName | string | Yes | ステップ名 | 必須、空文字不可 |
| Subsystem | string | No | サブシステムタイプ | ValidateSet、デフォルトTransactSql |
| SubsystemServer | string | No | Analysis Services サーバー名 | SSAS サブシステム時必須 |
| Command | string | No | 実行コマンド | - |
| CmdExecSuccessCode | int | No | CmdExec 成功コード | - |
| OnSuccessAction | string | No | 成功時アクション | QuitWithSuccess/QuitWithFailure/GoToNextStep/GoToStep |
| OnSuccessStepId | int | No | 成功時ジャンプ先ステップID | GoToStep 時のみ有効 |
| OnFailAction | string | No | 失敗時アクション | QuitWithSuccess/QuitWithFailure/GoToNextStep/GoToStep |
| OnFailStepId | int | No | 失敗時ジャンプ先ステップID | GoToStep 時のみ有効 |
| Database | string | No | 実行データベース | TransactSql 用 |
| DatabaseUser | string | No | データベースユーザー | Database と併用 |
| RetryAttempts | int | No | リトライ回数 | - |
| RetryInterval | int | No | リトライ間隔（分） | - |
| OutputFileName | string | No | 出力ファイルパス | - |
| Insert | switch | No | 既存ステップ間への挿入 | - |
| Flag | string[] | No | ジョブステップフラグ | ログ関連オプション |
| ProxyName | string | No | プロキシアカウント名 | - |
| Force | switch | No | 既存ステップを上書き | - |
| EnableException | switch | No | 例外処理の制御フラグ | - |

### 入力データソース

- ユーザー指定のパラメータ
- 既存ジョブオブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Name | string | ステップ名 |
| ID | int | ステップID（実行順序） |
| Parent | Job | 親ジョブオブジェクト |
| Subsystem | enum | サブシステムタイプ |
| Command | string | 実行コマンド |
| DatabaseName | string | データベース名 |
| DatabaseUserName | string | データベースユーザー名 |
| OnSuccessAction | enum | 成功時アクション |
| OnSuccessStep | int | 成功時ジャンプ先 |
| OnFailAction | enum | 失敗時アクション |
| OnFailStep | int | 失敗時ジャンプ先 |
| RetryAttempts | int | リトライ回数 |
| RetryInterval | int | リトライ間隔 |
| OutputFileName | string | 出力ファイルパス |
| ProxyName | string | プロキシ名 |
| JobStepFlags | enum | ステップフラグ |

### 出力先

PowerShell パイプラインへの出力（`Microsoft.SqlServer.Management.Smo.Agent.JobStep` オブジェクト）

## 処理フロー

### 処理シーケンス

```
1. パラメータ検証
   └─ OnSuccess/OnFail StepId と Action の整合性チェック
   └─ Analysis Services サブシステム用 SubsystemServer チェック
2. インスタンスループ開始
   └─ 各 SqlInstance に対して処理
3. SQL Server 接続
   └─ Connect-DbaInstance で接続確立
4. ジョブループ
   └─ 各 Job に対して処理
5. ジョブ存在確認
   └─ 指定ジョブの存在確認
6. SMO JobStep オブジェクト作成
   └─ ジョブを Parent として設定
7. ステップ名/ID 重複チェック
   └─ Force/Insert による処理分岐
8. プロパティ設定
   └─ 各パラメータに基づくプロパティ設定
9. ステップ作成
   └─ $jobStep.Create() および親ジョブの Alter()
10. 結果出力
    └─ 作成したステップを直接出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[パラメータ検証]
    B --> C{検証エラー?}
    C -->|Yes| D[Stop-Function で終了]
    C -->|No| E{SqlInstance ループ}
    E --> F[Connect-DbaInstance]
    F --> G{接続成功?}
    G -->|No| H[Stop-Function]
    H --> E
    G -->|Yes| I{Job ループ}
    I --> J{ジョブ存在?}
    J -->|No| K[Write-Message 警告]
    K --> I
    J -->|Yes| L[SMO JobStep 作成]
    L --> M{ステップ名重複?}
    M -->|Yes| N{Force 指定?}
    N -->|Yes| O[既存ステップ削除]
    N -->|No| P[Stop-Function でスキップ]
    O --> Q[プロパティ設定]
    M -->|No| Q
    P --> I
    Q --> R{StepId 重複?}
    R -->|Yes| S{Insert 指定?}
    S -->|Yes| T[既存ステップID再番号付け]
    S -->|No| U{Force 指定?}
    U -->|Yes| V[既存ステップ削除]
    U -->|No| W[Stop-Function でスキップ]
    T --> X[プロパティ詳細設定]
    V --> X
    R -->|No| X
    W --> I
    X --> Y[JobStep.Create]
    Y --> Z[Job.Alter]
    Z --> AA[出力]
    AA --> I
    I -->|終了| E
    E -->|終了| AB[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-500-01 | ステップ名一意性 | 同一ジョブ内でステップ名は一意（Force時は削除後再作成） | 常時 |
| BR-500-02 | GoToStep パラメータ制約 | OnSuccess/OnFailStepId は対応する Action が GoToStep の時のみ有効 | StepId 指定時 |
| BR-500-03 | Insert による再番号付け | Insert 指定時、指定 StepId 以降の既存ステップIDを+1 | Insert 指定時 |
| BR-500-04 | AG リスナー制限 | 可用性グループリスナー経由ではステップ作成不可 | AG リスナー接続時 |
| BR-500-05 | SSAS サブシステム要件 | AnalysisScripting/AnalysisCommand/AnalysisQuery 使用時は SubsystemServer 必須 | SSAS サブシステム時 |
| BR-500-06 | Database 存在確認 | 指定データベースはインスタンスに存在する必要がある | Database 指定時 |
| BR-500-07 | ProxyName 存在確認 | 指定プロキシはインスタンスに存在する必要がある | ProxyName 指定時 |

### 計算ロジック

**ステップID自動設定**:
```powershell
if (-not $StepId) {
    $jobStep.ID = $currentJob.JobSteps.Count + 1
}
```

**Insert 時のID再番号付け**:
```powershell
foreach ($tStep in $currentJob.JobSteps) {
    if ($tStep.Id -ge $Stepid) {
        $tStep.Id = ($tStep.ID) + 1
    }
    if ($tStep.OnFailureStepID -ge $StepId -and $tStep.OnFailureStepId -ne 0) {
        $tStep.OnFailureStepID = ($tStep.OnFailureStepID) + 1
    }
}
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ステップ作成 | msdb.dbo.sysjobsteps | INSERT | ジョブステップの作成 |
| ジョブ更新 | msdb.dbo.sysjobs | UPDATE | ジョブのステップ情報更新 |

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

#### msdb.dbo.sysjobsteps

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | step_id, step_name, subsystem, command, database_name, on_success_action など | SMO JobStep.Create() 経由 | |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | SQL Server への接続失敗 | Stop-Function で Continue |
| JobNotFound | ジョブ不存在 | 指定ジョブが存在しない | Write-Message 警告 |
| StepNameExists | ステップ名重複 | 同名ステップが存在（Force なし） | Stop-Function で Continue |
| StepIdExists | ステップID重複 | 同一IDが存在（Insert/Force なし） | Stop-Function で Continue |
| InvalidParameter | パラメータエラー | StepId と Action の不整合 | Stop-Function で終了 |
| DatabaseNotFound | DB不存在 | 指定データベースが存在しない | Stop-Function で Continue |
| ProxyNotFound | プロキシ不存在 | 指定プロキシが存在しない | Stop-Function で Continue |
| AGListener | AG制限 | AGリスナー経由での接続 | Stop-Function で Continue |

### リトライ仕様

リトライ処理は実装されていない。

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

各ステップは個別に作成される。SMO の Create() と Alter() メソッドで内部的にトランザクション管理。

## パフォーマンス要件

- 各インスタンスへの接続は順次処理
- Insert 時は既存ステップの再番号付けが発生

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

- SQL Server への接続には SqlCredential による認証情報指定が可能
- sysadmin 権限が必要
- ProxyName 指定により異なるセキュリティコンテキストでの実行が可能
- ShouldProcess（WhatIf/Confirm）をサポート

## 備考

- サポートするサブシステム:
  - TransactSql: T-SQL スクリプト（デフォルト）
  - PowerShell: PowerShell スクリプト
  - CmdExec: OS コマンド
  - Ssis: SSIS パッケージ
  - Distribution/LogReader/Merge/QueueReader/Snapshot: レプリケーション
  - AnalysisCommand/AnalysisQuery: Analysis Services
- Flag オプション:
  - AppendAllCmdExecOutputToJobHistory
  - AppendToJobHistory
  - AppendToLogFile
  - AppendToTableLog
  - LogToTableWithOverwrite
  - None
  - ProvideStopProcessEvent

---

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

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

### 推奨読解順序

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

SMO の JobStep オブジェクト構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | New-DbaAgentJobStep.ps1 | `public/New-DbaAgentJobStep.ps1` | 132-158行目の .OUTPUTS セクション |

**読解のコツ**: JobStep は親 Job オブジェクトへの参照を持ち、OnSuccessAction/OnFailAction で実行フロー制御を行う。

#### Step 2: パラメータと前処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | New-DbaAgentJobStep.ps1 | `public/New-DbaAgentJobStep.ps1` | 195-229行目のパラメータ定義、231-252行目の begin ブロック |

**主要処理フロー**:
1. **232行目**: Force による ConfirmPreference 設定
2. **234-238行目**: OnSuccessStepId と OnSuccessAction の整合性チェック
3. **240-244行目**: OnFailStepId と OnFailAction の整合性チェック
4. **246-251行目**: SSAS サブシステムの SubsystemServer 必須チェック

#### Step 3: ジョブステップ作成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaAgentJobStep.ps1 | `public/New-DbaAgentJobStep.ps1` | 254-453行目の process ブロック |

**主要処理フロー**:
- **265-270行目**: ジョブ存在チェック
- **272-287行目**: SMO JobStep オブジェクト作成（AG リスナーエラー処理含む）
- **291-306行目**: ステップ名重複チェックと Force 処理
- **309-340行目**: ステップID重複チェックと Insert/Force 処理
- **342-431行目**: 各プロパティの設定
- **435-447行目**: Create と Alter 処理

#### Step 4: プロパティ設定処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | New-DbaAgentJobStep.ps1 | `public/New-DbaAgentJobStep.ps1` | 342-431行目のプロパティ設定 |

**主要処理フロー**:
- **342-345行目**: Subsystem 設定
- **362-365行目**: OnSuccessAction 設定
- **382-390行目**: Database 存在チェックと設定
- **418-426行目**: ProxyName 存在チェックと設定
- **428-431行目**: Flag 設定

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

```
New-DbaAgentJobStep
    │
    ├─ begin ブロック
    │      ├─ Force による ConfirmPreference 設定
    │      ├─ OnSuccess/OnFail パラメータ検証
    │      └─ SSAS SubsystemServer 検証
    │
    ├─ Connect-DbaInstance
    │      └─ SMO 接続確立
    │
    ├─ $Server.JobServer.Jobs[$j]
    │      └─ ジョブオブジェクト取得
    │
    ├─ New-Object Microsoft.SqlServer.Management.Smo.Agent.JobStep
    │      └─ SMO JobStep オブジェクト作成
    │
    ├─ Remove-DbaAgentJobStep（Force/Insert 時）
    │      └─ 既存ステップ削除
    │
    ├─ プロパティ設定
    │      ├─ Subsystem, Command
    │      ├─ OnSuccessAction, OnFailAction
    │      ├─ Database, DatabaseUserName
    │      ├─ RetryAttempts, RetryInterval
    │      ├─ OutputFileName
    │      ├─ ProxyName
    │      └─ Flag
    │
    ├─ JobStep.Create()
    │      └─ ステップ作成
    │
    └─ Job.Alter()
           └─ ジョブ更新
```

### データフロー図

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

SqlInstance ─────────────┬─► Connect-DbaInstance ──────────────► SMO Server
SqlCredential ───────────┘                                              │
                                                                        ▼
Job ─────────────────────────► ジョブ存在チェック ◄─────────────────────┤
                                        │                               │
                                   存在しない?                          │
                                   │      │                             │
                                 Yes      No                            │
                                   │      │                             │
                              警告出力    ▼                             │
                                    New-Object JobStep                  │
                                         │                              │
StepName ────────────────────────► 名前重複チェック                     │
Force ───────────────────────────►   │                                  │
                                     ▼                                  │
StepId ──────────────────────────► ID重複/Insert 処理                   │
Insert ──────────────────────────►   │                                  │
                                     ▼                                  │
Subsystem ───────────────────────────┤                                  │
SubsystemServer ─────────────────────┤                                  │
Command ─────────────────────────────┤                                  │
OnSuccessAction ─────────────────────┤                                  │
OnSuccessStepId ─────────────────────┤                                  │
OnFailAction ────────────────────────┤                                  │
OnFailStepId ────────────────────────┤                                  │
Database ────────────────────────────┤                                  │
DatabaseUser ────────────────────────┤                                  │
RetryAttempts ───────────────────────┤                                  │
RetryInterval ───────────────────────┤                                  │
OutputFileName ──────────────────────┤                                  │
ProxyName ───────────────────────────┤                                  │
Flag ────────────────────────────────┘                                  │
                                     │                                  │
                                     ▼                                  │
                              JobStep.Create()                          │
                                     │                                  │
                                     ▼                                  │
                                Job.Alter()                             │
                                     │                                  │
                                     ▼                                  │
                               JobStep 出力 ────────────────► JobStep オブジェクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| New-DbaAgentJobStep.ps1 | `public/New-DbaAgentJobStep.ps1` | ソース | メイン機能実装 |
| Remove-DbaAgentJobStep.ps1 | `public/Remove-DbaAgentJobStep.ps1` | ソース | ステップ削除 |
| Get-DbaAgentJob.ps1 | `public/Get-DbaAgentJob.ps1` | ソース | ジョブ取得 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server 接続 |
| Stop-Function.ps1 | `internal/functions/Stop-Function.ps1` | ソース | エラー処理 |
| Write-Message.ps1 | `internal/functions/Write-Message.ps1` | ソース | ログ出力 |
