📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の4版が非表示) | |||
| 51行目: | 51行目: | ||
<br><br> | <br><br> | ||
== BULK | == テーブルの作成 == | ||
BULK INSERT文は、データの挿入のみを行うコマンドで、テーブルの作成機能は持っていない。<br> | |||
* | データを挿入する場合は、列の定義や制約などのテーブル構造が必要となる。<br> | ||
<br> | |||
<syntaxhighlight lang="tsql"> | |||
CREATE TABLE customers ( | |||
id INT, | |||
name VARCHAR(100), | |||
email VARCHAR(200) | |||
); | |||
</syntaxhighlight> | |||
<br><br> | |||
== 使用例 == | |||
==== カンマ区切りファイルのインポート ==== | |||
* FIRSTROWオプションでヘッダ行をスキップする。 | |||
* MAXERRORSオプションでエラー許容数を設定する。 | |||
* エラーログファイルを指定する。 (問題追跡が可能) | |||
<br> | |||
# CSVファイルの内容 | |||
John,Doe,30,New York | |||
Jane,Smith,25,Los Angeles | |||
<br> | |||
<syntaxhighlight lang="tsql"> | |||
BULK INSERT Employees | |||
FROM 'D:\Data\employees.csv' | |||
WITH | |||
( | |||
FIRSTROW = 2, /* ヘッダ行をスキップ */ | |||
FIELDTERMINATOR = ',', /* フィールド区切り文字 */ | |||
ROWTERMINATOR = '\n', /* 行区切り文字 */ | |||
MAXERRORS = 2, /* 許容するエラーの最大数 */ | |||
ERRORFILE = 'D:\Data\errors.txt' /* エラーログファイル */ | |||
); | |||
</syntaxhighlight> | |||
<br> | |||
==== タブ区切りファイルのインポート (日付フォーマット指定) ==== | |||
* DATE_FORMATで日付形式を明示的に指定する。 | |||
* FORMATオプションでCSV形式を指定する。 | |||
<br> | |||
# TSVファイルの内容 | |||
OrderID OrderDate CustomerID Amount | |||
1001 2024-01-01 CUST001 1500.50 | |||
<br> | |||
<syntaxhighlight lang="tsql"> | <syntaxhighlight lang="tsql"> | ||
BULK INSERT Orders | |||
FROM 'D:\Data\orders.txt' | |||
WITH | |||
( | |||
DATAFILETYPE = 'char', | |||
FIELDTERMINATOR = '\t', /* タブ区切り */ | |||
ROWTERMINATOR = '\n', | |||
FORMAT = 'CSV', /* CSVフォーマットを使用 */ | |||
DATE_FORMAT = 'yyyy-MM-dd' /* 日付フォーマットを指定 */ | |||
); | |||
</syntaxhighlight> | |||
<br> | |||
==== 固定長フォーマットファイルのインポート ==== | |||
* フォーマットファイルを使用して列幅を定義する。 | |||
* KEEPNULLSオプションでNULL値の処理を制御する。 | |||
<br> | |||
# データ例 (各フィールドが固定長) | |||
ID NAME DEPT | |||
001 JOHN SALES | |||
002 MARY IT | |||
<br> | |||
<syntaxhighlight lang="tsql"> | |||
BULK INSERT Employees | |||
FROM 'D:\Data\employees_fixed.txt' | |||
WITH | |||
( | |||
DATAFILETYPE = 'char', | |||
FORMATFILE = 'D:\Data\format.fmt', /* フォーマットファイルを指定 */ | |||
CODEPAGE = '65001', /* UTF-8エンコーディング */ | |||
KEEPNULLS /* NULL値を保持 */ | |||
); | |||
</syntaxhighlight> | |||
<br> | |||
==== XMLフォーマットファイルを使用したインポート ==== | |||
* 詳細なデータマッピングが可能になる。 | |||
* CHECK_CONSTRAINTSオプションで制約チェックを有効化する。 | |||
* FIRE_TRIGGERSオプションでトリガー処理を制御する。 | |||
<br> | |||
<syntaxhighlight lang="tsql"> | |||
/* より詳細なデータマッピングが必要な場合 */ | |||
BULK INSERT Products | |||
FROM 'D:\Data\products.txt' | |||
WITH | |||
( | |||
FORMATFILE = 'D:\Data\products_format.xml', | |||
CHECK_CONSTRAINTS, /* 制約チェックを有効化 */ | |||
FIRE_TRIGGERS, /* トリガーを発火 */ | |||
KEEPIDENTITY /* ID列の値を保持 */ | |||
); | |||
</syntaxhighlight> | |||
<br> | |||
==== バッチ処理によるBULK INSERT ==== | |||
* BATCHSIZEオプションとROWS_PER_BATCHオプションでパフォーマンス最適化する。 | |||
* TABLOCKオプションでロック戦略を制御する。 | |||
* ORDER句でデータの順序を指定する。 | |||
<br> | |||
<syntaxhighlight lang="tsql"> | |||
/* 大量データを分割してインポートする場合 */ | |||
BULK INSERT LargeTable | |||
FROM 'D:\Data\large_data.csv' | |||
WITH | |||
( | |||
BATCHSIZE = 1000, /* バッチサイズを指定 */ | |||
ROWS_PER_BATCH = 10000, /* バッチあたりの行数 */ | |||
TABLOCK, /* テーブルロックを使用 */ | |||
ORDER (OrderColumn ASC) /* データの順序を指定 */ | |||
); | |||
</syntaxhighlight> | |||
<br> | |||
==== 文字コードに関する使用例 ==== | |||
以下の例では、CSVファイル (カンマ区切り) をインポートしている。<br> | |||
<br> | |||
<syntaxhighlight lang="tsql"> | |||
/* 文字コードがShift-JISの場合 */ | |||
BULK INSERT T_Table | BULK INSERT T_Table | ||
FROM 'D:\UnicodeFile.txt' | |||
WITH ( | |||
DATAFILETYPE = 'char', | |||
FIELDTERMINATOR = ',' | |||
); | |||
GO | GO | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
<syntaxhighlight lang="tsql"> | <syntaxhighlight lang="tsql"> | ||
/* 文字コードがUNICODEの場合 (SQL Server 2014 R2以前) */ | |||
/* ただし、SQL Server 2014 R2以前では、下記のクエリを実行しても UTF-8形式のファイルは取り込めない */ | |||
/* (UTF-8固有の文字が無いUTF-8形式のファイルはインポートできる) */ | |||
BULK INSERT T_Table | BULK INSERT T_Table | ||
FROM 'D:\UnicodeFile.txt' | |||
WITH ( | |||
DATAFILETYPE = 'widechar', | |||
FIELDTERMINATOR = ',' | |||
); | |||
GO | GO | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
<syntaxhighlight lang="tsql"> | <syntaxhighlight lang="tsql"> | ||
/* 文字コードがUTF-8の場合 (SQL Server 2014 R2以降) */ | |||
/* SQL Server 2014 R2以降では、UTF-8形式のファイルをインポートすることが出来る */ | |||
BULK INSERT T_Table | BULK INSERT T_Table | ||
FROM 'D:\UnicodeFile.txt' | |||
WITH ( | |||
DATAFILETYPE = 'char', | |||
CODEPAGE = '65001', | |||
FIELDTERMINATOR = ',' | |||
); | |||
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> | ||