📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

188行目: 188行目:
         );
         );
  GO
  GO
</syntaxhighlight>
<br><br>
== 動的にテーブルを作成 ==
BULK INSERT文は、データの挿入のみを行うコマンドで、テーブルの作成機能は持っていない。<br>
データを挿入する場合は、列の定義や制約などのテーブル構造が必要となる。<br>
<br>
既存のテーブル構造が不明な場合は、データファイルの内容を確認して、適切な列の型とサイズを決定してからテーブルを作成する。<br>
<br>
また、データファイルの内容を分析してテーブルを作成するプロセスをSQLで自動化することができる。<br>
<br>
以下の例では、まず、CSVファイルを一時テーブルに読み込み、ヘッダ行とサンプルデータを分析してデータ型を推測している。<br>
次に、各データ型である数値型、日付型、文字列型 (長さに応じて適切なサイズを設定) を推測して、CREATE TABLE文を使用して動的に生成して実行している。<br>
最後に、作成されたテーブル構造を確認している。<br>
<br>
※注意<br>
* データ型の推測は最初の行のみを基に行われるため、完全な精度は保証されない。
* 大規模なデータセットの場合、より多くのサンプルを分析することを推奨する。
* 特殊な要件 (一意制約、外部キー等) は手動で追加する必要がある。
<br>
このSQLを実行した後、必要に応じてALTER TABLE文を使用して列定義を調整できる。<br>
<br>
<syntaxhighlight lang="tsql">
/* 一時テーブルを作成してCSVファイルを読み込む */
CREATE TABLE #TempRawData (
    LineContent NVARCHAR(MAX)
);
/* CSVファイルを一時テーブルに読み込む */
BULK INSERT #TempRawData
FROM 'C:\data\sample.csv'
WITH (
    ROWTERMINATOR = '\n'
);
/* ヘッダ行を取得 (1行目) */
DECLARE @HeaderLine NVARCHAR(MAX);
SELECT TOP 1 @HeaderLine = LineContent FROM #TempRawData;
/* データの1行目を取得 (実際のデータ形式を確認するため) */
DECLARE @SampleDataLine NVARCHAR(MAX);
SELECT TOP 1 @SampleDataLine = LineContent
FROM #TempRawData
WHERE LineContent != @HeaderLine;
/* 動的SQLを生成するための変数を宣言 */
DECLARE @CreateTableSQL NVARCHAR(MAX);
DECLARE @ColumnNames TABLE (
    ColumnName NVARCHAR(255),
    SampleValue NVARCHAR(MAX)
);
/* ヘッダーとサンプルデータを分割して@ColumnNamesに格納 */
;WITH SplitHeaders AS (
    SELECT value AS ColumnName, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNum
    FROM STRING_SPLIT(@HeaderLine, ',')
),
SplitData AS (
    SELECT value AS SampleValue, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNum
    FROM STRING_SPLIT(@SampleDataLine, ',')
)
INSERT INTO @ColumnNames
SELECT h.ColumnName,
        d.SampleValue
FROM SplitHeaders h
JOIN SplitData d ON h.RowNum = d.RowNum;
/* CREATE TABLE文を動的に生成 */
SET @CreateTableSQL = N'CREATE TABLE ImportedData (';
SELECT @CreateTableSQL = @CreateTableSQL +
    QUOTENAME(ColumnName) + ' ' +
    CASE
      WHEN ISNUMERIC(SampleValue) = 1 AND CHARINDEX('.', SampleValue) > 0
          THEN 'DECIMAL(18,2)'
      WHEN ISNUMERIC(SampleValue) = 1
          THEN 'INT'
      WHEN ISDATE(SampleValue) = 1
          THEN 'DATETIME'
      WHEN LEN(SampleValue) <= 50
          THEN 'NVARCHAR(50)'
      WHEN LEN(SampleValue) <= 255
          THEN 'NVARCHAR(255)'
      ELSE 'NVARCHAR(MAX)'
    END + ',' + CHAR(13)
FROM @ColumnNames;
/* 最後のカンマを削除して閉じカッコを追加 */
SET @CreateTableSQL = LEFT(@CreateTableSQL, LEN(@CreateTableSQL) - 2) + ')';
/* テーブルが既に存在する場合は削除 */
IF OBJECT_ID('ImportedData', 'U') IS NOT NULL DROP TABLE ImportedData;
/* 新しいテーブルを作成 */
EXEC sp_executesql @CreateTableSQL;
/* 一時テーブルをクリーンアップ */
DROP TABLE #TempRawData;
/* 作成されたテーブル定義を確認 */
SELECT
    c.name AS ColumnName,
    t.name AS DataType,
    c.max_length,
    c.precision,
    c.scale
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE object_id = OBJECT_ID('ImportedData');
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br><br>