# 画面設計書 180-クエリ実行

## 概要

本ドキュメントは、dbatools PowerShellモジュールの `Invoke-DbaQuery` コマンドの機能仕様を定義した画面設計書です。

### 本画面の処理概要

本コマンドは、1つ以上のSQL Serverインスタンスに対してT-SQLクエリ、スクリプト、ストアドプロシージャを実行し、パラメータ化クエリをサポートする汎用クエリ実行機能を提供します。

**業務上の目的・背景**：DBAや開発者は、レポート作成、メンテナンス作業、複数サーバーへのスクリプトデプロイなど、様々な目的でSQL Serverに対してカスタムクエリを実行する必要があります。本コマンドは、SQLインジェクション攻撃を防ぐセキュアなパラメータ化クエリ実行を提供し、複数インスタンスへの一括実行、ファイルやURLからのスクリプト読み込み、様々な出力形式をサポートする包括的なクエリ実行機能を提供します。

**画面へのアクセス方法**：PowerShellコンソールまたはスクリプトから `Invoke-DbaQuery` コマンドを実行します。SqlInstanceパラメータまたはGet-DbaDatabaseからのパイプライン入力を使用します。

**主要な操作・処理内容**：
1. クエリソースの決定（Query文字列、File、SqlObject）
2. 指定されたSQL Serverインスタンスまたはデータベースに接続
3. パラメータ化クエリの場合、SqlParameterを適用
4. クエリを実行（Invoke-DbaAsync経由）
5. 指定された形式（DataSet、DataTable、DataRow、PSObject、SingleValue）で結果を返却

**画面遷移**：本コマンドは `Get-DbaDatabase`、`Get-DbaRegServer` からパイプライン入力を受け取ることができます。出力結果は他のPowerShellコマンドにパイプで渡すことができます。

**権限による表示制御**：クエリ内容に応じた適切な権限が必要です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 174 | Invoke-DbaQuery | 主機能 | SQLクエリの実行 |

## 画面種別

コマンドライン出力（クエリ結果表示）

## URL/ルーティング

PowerShellコマンド: `Invoke-DbaQuery`

## 入出力項目

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|---|------|------|
| SqlInstance | DbaInstance[] | No | 対象SQL Serverインスタンス |
| SqlCredential | PSCredential | No | 認証用資格情報 |
| Database | string | No | 対象データベース |
| Query | string | Yes(Query) | 実行するT-SQLクエリ |
| QueryTimeout | int | No | クエリタイムアウト（秒） |
| File | object[] | Yes(File) | SQLスクリプトファイルパス/URL/ディレクトリ |
| SqlObject | SqlSmoObject[] | Yes(SMO) | スクリプト化して実行するSMOオブジェクト |
| As | string | No | 出力形式（DataSet、DataTable、DataRow、PSObject、PSObjectArray、SingleValue） |
| SqlParameter | psobject[] | No | パラメータ化クエリ用パラメータ |
| CommandType | CommandType | No | コマンドタイプ（Text、StoredProcedure、TableDirect） |
| AppendServerInstance | switch | No | 結果にサーバーインスタンス名列を追加 |
| MessagesToOutput | switch | No | PRINTメッセージを出力に含める |
| InputObject | Database[] | No | パイプライン入力（Databaseオブジェクト） |
| ReadOnly | switch | No | ReadOnly接続インテントを使用 |
| NoExec | switch | No | 構文検証のみ実行（実際には実行しない） |
| QuotedIdentifier | switch | No | SET QUOTED_IDENTIFIER ONを付加 |
| AppendConnectionString | string | No | 追加の接続文字列パラメータ |
| EnableException | switch | No | 例外処理モードの有効化 |

## 表示項目

出力形式（Asパラメータ）によって異なります：

### DataSet
| 項目名 | 型 | 説明 |
|--------|---|------|
| (DataSet) | System.Data.DataSet | クエリ結果を含むDataSetオブジェクト |

### DataTable
| 項目名 | 型 | 説明 |
|--------|---|------|
| (DataTable[]) | System.Data.DataTable[] | 各結果セットのDataTable配列 |

### DataRow（デフォルト）
| 項目名 | 型 | 説明 |
|--------|---|------|
| (DataRow[]) | System.Data.DataRow[] | クエリ結果の各行 |

### PSObject / PSObjectArray
| 項目名 | 型 | 説明 |
|--------|---|------|
| (PSObject) | PSObject | DBNullが$nullに変換された行オブジェクト |

### SingleValue
| 項目名 | 型 | 説明 |
|--------|---|------|
| (Object) | System.Object | 最初の行の最初の列の値 |

## イベント仕様

### 1-コマンド実行

1. パラメータセット（Query/File/SMO）を判定
2. Fileパラメータの場合、ファイル/URL/ディレクトリからSQLを読み込み
3. SqlObjectパラメータの場合、Export-DbaScriptでスクリプト化
4. InputObject（データベース）またはSqlInstanceに対してループ
5. 接続コンテキストを取得または作成
6. Invoke-DbaAsyncでクエリを実行
7. 指定された形式で結果を返却
8. 非プール接続の場合、切断処理

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| クエリ実行 | クエリ依存 | SELECT/INSERT/UPDATE/DELETE | クエリ内容に依存 |

### テーブル別更新項目詳細

本コマンドは汎用クエリ実行機能のため、実行されるクエリによって更新内容が異なります。

## メッセージ仕様

| メッセージID | 種別 | 条件 | メッセージ内容 |
|-------------|------|------|--------------|
| M001 | Error | SqlParameter無効 | "SqlParameter only accepts a single hashtable or Microsoft.Data.SqlClient.SqlParameter" |
| M002 | Error | ファイルが見つからない | "Directory not found" / "Directory not found." |
| M003 | Error | ファイル取得失敗 | "Failed to download file {item}" |
| M004 | Error | パス解決失敗 | "Failed to resolve path: {item}" |
| M005 | Error | 入力タイプ不明 | "Unkown input type: {type}" |
| M006 | Error | パラメータ競合 | "You can't use -Database with piped databases" / "You can't use -SqlInstance with piped databases" |
| M007 | Error | 入力なし | "Please provide either SqlInstance or InputObject" |
| M008 | Warning | DBアクセス不可 | "Database {db} is not accessible. Skipping." |
| M009 | Error | 実行失敗 | "[{db/instance}] Failed during execution" |
| M010 | Error | 接続失敗 | "Failure" |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| SqlParameter形式エラー | Stop-Functionでエラーを出力して終了 |
| ファイル取得失敗 | Stop-Functionでエラーを出力して終了 |
| 接続失敗 | Stop-Functionでエラーを出力し、次のインスタンスに継続 |
| クエリ実行失敗 | Stop-Functionでエラーを出力し、次のインスタンスに継続 |

## 備考

- GOバッチセパレータ、XQuery、SQLCMDコマンドをサポート
- パラメータ化クエリはSQLインジェクション対策として推奨
- ReadOnlyスイッチは可用性グループのリスナーでセカンダリレプリカへのクエリに有用
- Always Encryptedカラムをサポート（Connect-DbaInstanceで-AlwaysEncryptedを使用）
- フィルターインデックスを持つテーブルへのINSERT/UPDATE/DELETEにはQuotedIdentifierスイッチが必要

---

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

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

### 推奨読解順序

#### Step 1: パラメータセットを理解する

3つの排他的なパラメータセット（Query、File、SMO）を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | 224-255行目：パラメータ定義 |

**読解のコツ**: ParameterSetNameでQuery、File、SMOの3つのセットが定義されています。

#### Step 2: beginブロックを理解する

ファイル/URL/SMOオブジェクトからSQLを読み込む処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | 257-416行目：beginブロック |

**主要処理フロー**:
1. **260-266行目**: SqlParameterの検証
2. **268-296行目**: Invoke-DbaAsync用のsplatパラメータ準備
3. **298-389行目**: Fileパラメータの処理（ファイル/URL/ディレクトリ）
4. **391-415行目**: SqlObjectパラメータの処理（Export-DbaScriptでスクリプト化）

#### Step 3: processブロックを理解する

接続とクエリ実行の処理フローを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | 418-549行目：processブロック |

**主要処理フロー**:
1. **420-431行目**: パラメータ競合チェック
2. **434-459行目**: InputObject（Database）に対する処理
3. **460-549行目**: SqlInstanceに対する処理
4. **500-525行目**: 接続の再利用判定ロジック（重要なコメント付き）
5. **530-543行目**: クエリ実行

#### Step 4: 接続再利用ロジックを理解する

複雑な接続管理ロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | 500-525行目：接続再利用判定 |

**主要処理フロー**:
- **500-505行目**: 接続再利用可能な条件を定義
  - Server SMOオブジェクトである
  - ReadOnlyインテントが要求されていない
  - Databaseが未指定または現在の接続データベースと一致
  - AppendConnectionStringが未使用
  - ConnectAsUserNameが未設定
- **506-508行目**: 条件を満たす場合は既存接続を再利用
- **509-524行目**: 条件を満たさない場合は新規接続を作成（NonPooledConnection）

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

```
Invoke-DbaQuery
    |
    +-- begin
    |      |
    |      +-- SqlParameter検証
    |      |
    |      +-- splatパラメータ準備
    |      |
    |      +-- File処理
    |      |      |
    |      |      +-- ディレクトリ検索
    |      |      +-- URL取得（Invoke-TlsWebRequest）
    |      |      +-- ファイルパス解決
    |      |
    |      +-- SqlObject処理
    |             |
    |             +-- Export-DbaScript
    |
    +-- process
           |
           +-- InputObject処理
           |      |
           |      +-- Invoke-DbaAsync
           |
           +-- SqlInstance処理
                  |
                  +-- 接続再利用判定
                  |
                  +-- Connect-DbaInstance (必要時)
                  |
                  +-- Invoke-DbaAsync
                  |
                  +-- Disconnect-DbaInstance (必要時)
```

### データフロー図

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

Query/File/SqlObject  ---> begin: SQLソース準備  ---> $files / $query

SqlInstance/           ---> process:
InputObject                  |
                            v
                   接続取得/再利用判定
                            |
                            v
                   Invoke-DbaAsync
                   (クエリ実行)
                            |
                            v
                   As パラメータに応じた
                   結果形式変換
                            |
                            v
                   DataSet / DataTable /   ---> パイプライン出力
                   DataRow / PSObject /
                   SingleValue
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | ソース | メイン関数実装 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続処理 |
| Disconnect-DbaInstance.ps1 | `public/Disconnect-DbaInstance.ps1` | ソース | 接続切断処理 |
| Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | ソース | SMOオブジェクトのスクリプト化 |
| Invoke-DbaAsync.ps1 | `internal/functions/Invoke-DbaAsync.ps1` | ソース | 非同期クエリ実行エンジン |
