# 機能設計書 674-Write-DbaDbTableData

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおける `Write-DbaDbTableData` コマンドレットの機能設計を記載する。この機能はSqlBulkCopyを使用して高速バルクインサートを実行し、様々なデータソースからSQL Serverテーブルへデータをインポートする。

### 本機能の処理概要

**業務上の目的・背景**：大量のデータをSQL Serverにインポートする際、通常のINSERT文では処理速度が遅く非効率である。本機能はSqlBulkCopyを使用することで、CSVファイル、DataTable、DataSet、PowerShellオブジェクトなど様々なデータソースから最適なパフォーマンスでバルクインサートを実行する。データ移行、ETLプロセス、大規模データセットのインポートに広く使用される。

**機能の利用シーン**：
- CSVファイルからSQL Serverテーブルへの大量データインポート
- ETLプロセスでのステージングテーブルへのデータロード
- PowerShellオブジェクト（例: Get-Process結果）のデータベース保存
- 異なるSQL Serverインスタンス間でのデータ移行
- Azure SQL Databaseへのデータインポート

**主要な処理内容**：
1. 接続確立とテーブル名解析（1〜3パート名対応）
2. テーブル存在確認（存在しない場合はAutoCreateTable時に作成）
3. スキーマ自動作成（必要に応じて）
4. SqlBulkCopyオブジェクトの構成（オプション、バッチサイズ等）
5. データ型変換（PowerShell → SQL Server）
6. バルクコピー実行と進捗表示
7. 後処理（接続クローズ、一時テーブル対応）

**関連システム・外部連携**：
- Microsoft.Data.SqlClient.SqlBulkCopy APIを使用
- ConvertTo-DbaDataTableでデータ型変換

**権限による制御**：対象テーブルへのINSERT権限、AutoCreateTable時はCREATE TABLE/SCHEMA権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コマンドライン | 主画面 | PowerShellコンソールまたはスクリプトから実行 |

## 機能種別

CRUD操作（Create/Insert）/ バルクロード / ETL処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter | Yes | 接続先SQL Serverインスタンス | 有効なインスタンス名 |
| SqlCredential | PSCredential | No | 代替認証情報 | 有効な資格情報 |
| Database | Object | No | 対象データベース | 3パート名使用時は省略可 |
| InputObject | Object | Yes | インポートデータ（DataTable, DataSet, CSV, オブジェクト） | パイプライン入力対応 |
| Table | String | Yes | 対象テーブル名（1-3パート名対応） | 有効なテーブル名 |
| Schema | String | No | スキーマ名（デフォルト: dbo） | 有効なスキーマ名 |
| BatchSize | Int | No | バッチサイズ（デフォルト: 50,000） | 正の整数 |
| NotifyAfter | Int | No | 進捗通知間隔（デフォルト: 5,000） | 正の整数 |
| AutoCreateTable | Switch | No | テーブル自動作成 | - |
| NoTableLock | Switch | No | テーブルロック無効化 | - |
| CheckConstraints | Switch | No | 制約チェック有効化 | - |
| FireTriggers | Switch | No | トリガー発火有効化 | - |
| KeepIdentity | Switch | No | Identity値保持 | - |
| KeepNulls | Switch | No | NULL値保持 | - |
| Truncate | Switch | No | 事前データ削除 | - |
| BulkCopyTimeOut | Int | No | タイムアウト秒数（デフォルト: 5,000） | 正の整数 |
| ColumnMap | Hashtable | No | カラムマッピング | @{SourceColumn='DestColumn'} |
| UseDynamicStringLength | Switch | No | 動的文字列長使用 | - |
| EnableException | Switch | No | 例外有効化 | - |

### 入力データソース

- CSVファイル（Import-Csv経由）
- System.Data.DataTable
- System.Data.DataSet
- System.Data.DataRow
- PowerShellオブジェクト（ConvertTo-DbaDataTable経由で変換）

## 出力仕様

### 出力データ

本コマンドはパイプラインへのオブジェクト出力を行わない。進捗情報はWrite-Progressで表示される。

### 出力先

- Write-Progress（進捗表示）
- Write-Message（詳細ログ）

## 処理フロー

### 処理シーケンス

```
1. begin{}ブロック
   └─ 接続コンテキスト取得
   └─ テーブル名解析（Get-ObjectNameParts）
   └─ データベース名確定
   └─ サーバー接続（Connect-DbaInstance）
   └─ FQTN（完全修飾テーブル名）構築
   └─ テーブル存在確認
   └─ SqlBulkCopyオブジェクト生成
   └─ オプション設定（TableLock, CheckConstraints等）
   └─ PS→SQLデータ型マッピング定義
   └─ ConvertTo-DbaDataTable準備（SteppablePipeline）
2. process{}ブロック
   └─ InputObjectタイプ判定
   └─ DataSet/DataTable: 直接処理
   └─ その他: ConvertTo-DbaDataTable経由変換
   └─ AutoCreateTable時: New-Table呼び出し
   └─ Invoke-BulkCopy実行
3. end{}ブロック
   └─ SteppablePipelineからDataTable取得
   └─ 最終バルクコピー実行
   └─ リソースクリーンアップ
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[テーブル名解析]
    B --> C{解析成功?}
    C -->|No| D[エラー終了]
    C -->|Yes| E[サーバー接続]
    E --> F[FQTN構築]
    F --> G{テーブル存在?}
    G -->|No| H{AutoCreateTable?}
    H -->|No| I[エラー終了]
    H -->|Yes| J[テーブル作成待機]
    G -->|Yes| K[SqlBulkCopy構成]
    J --> K
    K --> L[process{}開始]
    L --> M{InputObjectタイプ}
    M -->|DataSet/DataTable| N[直接処理]
    M -->|その他| O[ConvertTo-DbaDataTable]
    N --> P{テーブル存在?}
    O --> P
    P -->|No| Q[New-Table]
    P -->|Yes| R[Invoke-BulkCopy]
    Q --> R
    R --> S[end{}処理]
    S --> T[リソースクリーンアップ]
    T --> U[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | テーブル名必須 | Tableパラメータは必須 | 常時 |
| BR-002 | データベース解決 | 3パート名からDB取得、または-Database指定 | テーブル名解析時 |
| BR-003 | 一時テーブル処理 | #で始まるテーブルはtempdb.dboに配置 | 一時テーブル指定時 |
| BR-004 | Azure 3パート名制限 | Azure SQLでは3パート名不可 | ServerType判定 |
| BR-005 | デフォルトTableLock | NoTableLock未指定時はTABLOCKヒント使用 | デフォルト動作 |
| BR-006 | スキーマ自動作成 | 存在しないスキーマはdbo所有で作成 | AutoCreateTable時 |

### 計算ロジック

**データ型マッピング（PS → SQL）**:
| PowerShell型 | SQL Server型 |
|-------------|--------------|
| System.Int32 | int |
| System.Int64 | bigint |
| System.Decimal | decimal(38,5) |
| System.Double | float |
| System.String | nvarchar(MAX) |
| System.DateTime | datetime2 |
| System.Boolean | bit |
| System.Guid | uniqueidentifier |
| System.Byte[] | varbinary(MAX) |

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| テーブル作成 | 指定テーブル | CREATE TABLE | AutoCreateTable時 |
| スキーマ作成 | sys.schemas | CREATE SCHEMA | スキーマ未存在時 |
| データ削除 | 指定テーブル | TRUNCATE TABLE | Truncate指定時 |
| データ挿入 | 指定テーブル | BULK INSERT | SqlBulkCopy経由 |

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

#### 指定テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| BULK INSERT | 入力データのカラム | SqlBulkCopy経由 | バッチ単位実行 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | テーブル名解析エラー | 無効なテーブル名形式 | 正しい形式で指定 |
| - | テーブル不存在エラー | テーブル未存在かつAutoCreateTableなし | AutoCreateTable指定またはテーブル事前作成 |
| - | 接続エラー | SQL Server接続不可 | 接続情報確認 |
| - | バルクコピーエラー | データ型不一致等 | ColumnMapまたはデータ確認 |
| - | タイムアウト | BulkCopyTimeOut超過 | タイムアウト値増加 |

### リトライ仕様

エラー発生時のリトライは実装されていない。

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

SqlBulkCopyはバッチ単位で暗黙的トランザクションを使用。明示的トランザクション制御は行わない。

## パフォーマンス要件

- BatchSizeデフォルト: 50,000行
- 推奨: 幅広テーブルは5,000-10,000、狭いテーブルはより大きな値
- BulkCopyTimeOutデフォルト: 5,000秒（約83分）
- TABLOCKヒント（デフォルト）で最高パフォーマンス

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

- SqlCredentialパラメータで資格情報を安全に渡すことが可能
- AutoCreateTableで作成されるスキーマはdbo所有
- ConfirmImpact=Lowだが、Truncate時は確認あり

## 備考

- DataSet入力が最も効率的（単一SqlBulkCopy呼び出し）
- パイプライン直接入力は各行がDataRowとして処理されるため低速
- 一時テーブル使用時はNonPooled接続が必要

---

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

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

### 推奨読解順序

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

PS→SQLデータ型マッピングとSqlBulkCopyOptions構造を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Write-DbaDbTableData.ps1 | `public/Write-DbaDbTableData.ps1` | 639-682行目: $PStoSQLTypes定義 |
| 1-2 | Write-DbaDbTableData.ps1 | `public/Write-DbaDbTableData.ps1` | 576-593行目: SqlBulkCopyOptions構築 |

**読解のコツ**: $PStoSQLTypesハッシュテーブルはNew-Table関数内でAutoCreateTable時のカラム型決定に使用される。

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

begin{}ブロックでの初期化処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Write-DbaDbTableData.ps1 | `public/Write-DbaDbTableData.ps1` | 218-703行目: begin{}ブロック全体 |
| 2-2 | Write-DbaDbTableData.ps1 | `public/Write-DbaDbTableData.ps1` | 448-549行目: テーブル名解析とFQTN構築 |

**主要処理フロー**:
1. **448-453行目**: Get-ObjectNamePartsでテーブル名解析
2. **500-549行目**: FQTN（完全修飾テーブル名）構築
3. **551-573行目**: テーブル存在確認
4. **605-637行目**: SqlBulkCopyオブジェクト生成・イベント登録

#### Step 3: バルクコピー実行を理解する

内部関数Invoke-BulkCopyとNew-Tableを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Write-DbaDbTableData.ps1 | `public/Write-DbaDbTableData.ps1` | 244-296行目: Invoke-BulkCopy関数 |
| 3-2 | Write-DbaDbTableData.ps1 | `public/Write-DbaDbTableData.ps1` | 298-438行目: New-Table関数 |

**主要処理フロー**:
- **271行目**: SqlBulkCopy.WriteToServer()呼び出し
- **279-289行目**: ColumnMapping処理
- **354-380行目**: スキーマ自動作成
- **395-424行目**: カラム定義とデータ型決定

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

```
Write-DbaDbTableData
    │
    ├─ [begin] 初期化
    │      ├─ Get-ObjectNameParts (テーブル名解析)
    │      ├─ Connect-DbaInstance
    │      └─ SqlBulkCopy構成
    │
    ├─ [process] データ処理
    │      ├─ DataSet/DataTable → 直接処理
    │      │      ├─ New-Table (AutoCreateTable時)
    │      │      └─ Invoke-BulkCopy
    │      │             └─ SqlBulkCopy.WriteToServer()
    │      │
    │      └─ その他 → ConvertTo-DbaDataTable (SteppablePipeline)
    │
    └─ [end] 終了処理
           ├─ SteppablePipeline.End() → DataTable取得
           ├─ New-Table (AutoCreateTable時)
           ├─ Invoke-BulkCopy
           └─ Disconnect-DbaInstance
```

### データフロー図

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

Import-Csv ─────────────────┐
DataTable ──────────────────┼──▶ [InputObject判定]
DataSet ────────────────────┤
PowerShell Object ──────────┘
                                         │
                   ┌─────────────────────┼─────────────────────┐
                   ▼                     ▼                     ▼
            [DataSet]            [DataTable/Row]         [その他]
                   │                     │                     │
                   ▼                     ▼                     ▼
            直接処理              直接処理           ConvertTo-DbaDataTable
                   │                     │                     │
                   └─────────────────────┴─────────────────────┘
                                         │
                                         ▼
                              {テーブル存在確認}
                                         │
                              ┌──────────┴──────────┐
                              ▼                      ▼
                       [未存在]                  [存在]
                              │                      │
                              ▼                      │
                       New-Table                     │
                              │                      │
                              └──────────┬───────────┘
                                         │
                                         ▼
                              Invoke-BulkCopy
                                         │
                                         ▼
                              SqlBulkCopy.WriteToServer()
                                         │
                                         ▼
                              [SQL Server Table]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Write-DbaDbTableData.ps1 | `public/Write-DbaDbTableData.ps1` | ソース | メイン機能実装 |
| ConvertTo-DbaDataTable.ps1 | `public/ConvertTo-DbaDataTable.ps1` | ソース | データ型変換 |
| Get-ObjectNameParts.ps1 | `private/functions/Get-ObjectNameParts.ps1` | ソース | テーブル名解析 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | 接続処理 |
| Write-DbaDbTableData.Tests.ps1 | `tests/Write-DbaDbTableData.Tests.ps1` | テスト | 単体テスト |
