2 に答える
(少なくとも) 2 つのオプションがあります。
- 好みのスクリプト言語を使用して、ファイルを SQL Server の外部で 2 つの個別のファイルに分割します。1 つはヘッダー行、もう 1 つは詳細行です。次に、2 つの
BULK INSERT
ステートメントを使用して、それらを 2 つの異なるテーブルにロードします。 - SSIS とスクリプト タスクを使用して、ファイルを 2 つのデータ フローに分割し、パッケージ内でそれぞれを個別に処理します。
個人的にはオプション 1 を使用しますが、はるかに簡単です。また、データを一時テーブルにロードする理由はありません。このデータをロードするためだけに永続的なテーブル (またはテーブル) を作成します。これは、作業がはるかに簡単です。
Pondlife へのアドバイスに感謝します。私は自分の質問に対する答えを得ました。どうぞ;
ご存知のように、ヘッダーと詳細を同時に含むこのテキスト ファイルがあります。
HR|001580/06|RG|2013/11/01 12:00|BG|3573|001580| IT|001580/01|1|00147066||1200|852.3|830.3|1.35|UNIDAD|0|31/12/2014 00:00 IT|001580/02|1|00147066||200|852.3|830.3|1.35| UNIDAD|1|2014/12/31 00:00 IT|001580/03|1|00147066||100|852.3|830.3|1.35|UNIDAD|55|2014/12/31 00:00 IT|001580/04|2 |00254276||200|852.3|830.3|1.35|UNIDAD|0|31/12/2014 00:00 IT|001580/05|3|00305359||1700|852.3|830.3|1.35|UNIDAD|0|31/12 /2014 00:00 IT|001580/06|3|00305359||300|852.3|830.3|1.35|UNIDAD|1|2014/12/31 00:00
だから私はする必要があります:
- ファイルを読む
- ヘッダーを table1 に挿入します
- 詳細を table2 に挿入します
最初のステップでは、テーブルを作成してから、Sql BulkInsert を使用します
CREATE TABLE #ImportData
(
Field VARCHAR(max)
)
-- Insert the data into the first table
BULK INSERT #ImportData
FROM 'PATH FILE'
WITH
(
ROWTERMINATOR = '\n'
)
私はこのようなものを手に入れました。
行に区切り記号 ( | ) があることがわかります。これは、各テーブルのフィールド (HR - ヘッダー、IT - 詳細) を意味します。
次に、2 番目と 3 番目のステップでは、各テーブルに行を挿入する必要がありますが、各行の各フィールドを分離する必要もあるため、文字列と区切り文字を受け取り、文字列の各フィールドを含むテーブルを返すプロシージャを作成します。フィールドを動的に作成しました。
プロシージャを作成する場合は、最初にこれを実行する必要があります
SET QUOTED_IDENTIFIER OFF
。次に、作成できます。
--EXEC spSplit
-- @InputString = 'IT|001580/01|1|00147066||1200|852.3|830.3|1.35|QUANTITY|0|31/12/2014 00:00', -- VARCHAR(max)
-- @Delimiter = '|' -- VARCHAR(50)
--SET QUOTED_IDENTIFIER OFF
ALTER PROCEDURE spSplit
-- =============================================
-- Author: Gabriel Jiménez
-- Create date: 2013-01-16
-- Description: Procedimiento creado para retornar
-- valores de cada campo de una cadena delimitada
-- =============================================
@InputString NVARCHAR(max),
@Delimiter VARCHAR(50)
AS
BEGIN
SET QUOTED_IDENTIFIER OFF
CREATE TABLE #Items (Field1 VARCHAR(max))
DECLARE @Item VARCHAR(max)
DECLARE @ItemList VARCHAR(max)
DECLARE @DelimIndex INT
DECLARE @PositionField INT
DECLARE @SqlTable VARCHAR(max)
DECLARE @SqlUpdate VARCHAR(max)
SET @ItemList = @InputString
SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
SET @PositionField = 0
WHILE (@DelimIndex != 0)
BEGIN
SET @SqlTable = "ALTER TABLE #Items ADD Field"
SET @SqlUpdate = "UPDATE #Items SET Field"
-- Set positions Rows and Fields
SET @PositionField = @PositionField + 1
SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex)
IF @PositionField = 1
BEGIN
-- Insert the first data into the first field created on the table
INSERT INTO #Items (Field1) VALUES ( @Item )
END
ELSE
BEGIN
-- Create a dynamic table for the @InputString
SET @SqlTable = @SqlTable + CONVERT(VARCHAR, @PositionField)+ " VARCHAR(MAX)"
EXEC(@SqlTable)
SET @SqlUpdate = @SqlUpdate +
CONVERT(VARCHAR, @PositionField) + " = '" +
CONVERT(VARCHAR, @Item) +"'"
EXEC(@SqlUpdate)
END
-- Set @ItemList = @ItemList minus one less item
SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)-@DelimIndex)
SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
END -- End WHILE
IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString
BEGIN
SET @SqlTable = "ALTER TABLE #Items ADD Field"
SET @SqlUpdate = "UPDATE #Items SET Field"
SET @SqlTable = @SqlTable + CONVERT(VARCHAR, @PositionField+1)+ " VARCHAR(MAX)"
EXEC(@SqlTable)
SET @SqlUpdate = @SqlUpdate +
CONVERT(VARCHAR, @PositionField+1) + " = '" +
CONVERT(VARCHAR, @ItemList) +"'"
EXEC(@SqlUpdate)
END
-- No delimiters were encountered in @InputString, so just return @InputString
ELSE
BEGIN
SET @SqlTable = "ALTER TABLE #Items ADD Field"
SET @SqlUpdate = "UPDATE #Items SET Field"
SET @SqlTable = @SqlTable + CONVERT(VARCHAR, @PositionField+1)+ " VARCHAR(MAX)"
EXEC(@SqlTable)
SET @SqlUpdate = @SqlUpdate +
CONVERT(VARCHAR, @PositionField+1) + " = '" +
CONVERT(VARCHAR, @InputString) +"'"
EXEC(@SqlUpdate)
END
SELECT * FROM #Items
SET QUOTED_IDENTIFIER ON
END -- End Procedure
GO
手順を実行するために最初の 3 行をコメントすると、次のような結果が得られます。
まだ終了していません。ファイルを読み取り、フィールドを返すプロシージャを作成します。次に、各テーブルに挿入する必要があります。そのために、静的フィールドを持つ 2 つの一時テーブルを作成します。各テーブルのフィールドを知っているからです。 #ImpoData テーブルの各行を読み取るための Cursor を作成します。
CREATE TABLE #Header
(
Field1 VARCHAR(max),
Field2 VARCHAR(max),
Field3 VARCHAR(max),
Field4 VARCHAR(max),
Field5 VARCHAR(max),
Field6 VARCHAR(max),
Field7 VARCHAR(max),
Field8 VARCHAR(max)
)
-- Detail table is for the detail items
CREATE TABLE #Detail
(
Field1 VARCHAR(max),
Field2 VARCHAR(max),
Field3 VARCHAR(max),
Field4 VARCHAR(max),
Field5 VARCHAR(max),
Field6 VARCHAR(max),
Field7 VARCHAR(max),
Field8 VARCHAR(max),
Field9 VARCHAR(max),
Field10 VARCHAR(max),
Field11 VARCHAR(max),
Field12 VARCHAR(max)
)
DECLARE @Field NVARCHAR(max)
DECLARE Header CURSOR
FOR SELECT Field
FROM #ImportData
WHERE SUBSTRING(Field,1,2) = 'HR'
OPEN Header
FETCH NEXT FROM Header INTO @Field
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO #Header
EXEC spSplit @Field, '|'
FETCH NEXT FROM Header INTO @Field
END
CLOSE Header
DEALLOCATE Header
--Detail
--DECLARE @f NVARCHAR(max)
DECLARE Detail CURSOR
FOR SELECT Field
FROM #ImportData
WHERE SUBSTRING(Field,1,2) = 'IT'
OPEN Detail
FETCH NEXT FROM Detail INTO @Field
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO #Detail
EXEC spSplit @Field, '|'
FETCH NEXT FROM Detail INTO @Field
END
CLOSE Detail
DEALLOCATE Detail
--SELECT * FROM #ImportData
SELECT * FROM #Header
SELECT * FROM #Detail
DROP TABLE #ImportData
DROP TABLE #Header
DROP TABLE #Detail
その後、すべてのピースを同じクエリに配置すると、これが得られます。
必要に応じて。
分割のアドバイスをくれた Pondlife にもう一度感謝します。