将文本文件导入sql Server

时间:2013-01-16 16:04:31

标签: sql-server-2008

我已经阅读了一个带有批量语法的文本文件,但之后我发现了另一个问题:在我的文本文件中它有相同的标题和详细信息,所以我现在的问题是如何将标题放在{{ 1}}和table1中的详细信息?

我创建的另一件事只是table2用于放置我的所有行(标题和细节),但它们有field1,但标题有7个字段,详细信息有11个字段,所以另一个问题是因为我无法创建一个具有确切字段的表来放置我的详细信息和标题。

这是我正在阅读的文本文件的一个示例:

  

HR | 001580/06 | RG | 11/01/2013 12:00 | BG | 3573 | 001580   IT | 001580/01 | 1 | 00147066 || 1200 | 852.3 | 830.3 | 1.35 |团结报| 0 | 31/12/2014   00:00   IT | 001580/02 | 1 | 00147066 || 200 | 852.3 | 830.3 | 1.35 |团结报| 1 | 31/12/2014   00:00   IT | 001580/03 | 1 | 00147066 || 100 | 852.3 | 830.3 | 1.35 |团结报| 55 | 31/12/2014   00:00   IT | 001580/04 | 2 | 00254276 || 200 | 852.3 | 830.3 | 1.35 |团结报| 0 | 31/12/2014   00:00   IT | 001580/05 | 3 | 00305359 || 1700 | 852.3 | 830.3 | 1.35 |团结报| 0 | 31/12/2014   00:00   IT | 001580/06 | 3 | 00305359 || 300 | 852.3 | 830.3 | 1.35 |团结报| 1 | 31/12/2014   00:00

这是我的查询...

FIELDTERMINATOR = ‘|’

这是第一个查询它是标题

CREATE TABLE #temp
(
    campo1 VARCHAR(max)
)
BULK INSERT #temp
FROM ”
WITH
(
    FIELDTERMINATOR = ‘|’,
    ROWTERMINATOR = ‘\n’
)

这是第一次查询它是为了细节

SELECT *
FROM #temp
WHERE SUBSTRING(campo1,1,2) = ‘HR’

如何分隔标题和详细信息的字段?

2 个答案:

答案 0 :(得分:0)

有(至少)两个选项:

  1. 使用您首选的脚本语言将文件拆分为SQL Server外部的两个单独文件;一个带有标题行,另一个带有详细信息行。然后使用两个BULK INSERT语句将它们加载到两个不同的表中
  2. 使用SSIS和脚本任务将文件拆分为两个数据流,并在包中单独处理每个数据流
  3. 我个人会使用选项1,这样会容易得多。并且没有理由将数据加载到临时表中,我会创建一个永久表(或多个表)来加载这些数据。这更容易使用。

答案 1 :(得分:0)

感谢Pondlife的建议,我得到了自己问题的答案。 我们走了;

我们知道我有这个文本文件同时具有标题和细节

  

HR | 001580/06 | RG | 11/01/2013 12:00 | BG | 3573 | 001580 |   IT | 001580/01 | 1 | 00147066 || 1200 | 852.3 | 830.3 | 1.35 |团结报| 0 | 31/12/2014   00:00   IT | 001580/02 | 1 | 00147066 || 200 | 852.3 | 830.3 | 1.35 |团结报| 1 | 31/12/2014   00:00   IT | 001580/03 | 1 | 00147066 || 100 | 852.3 | 830.3 | 1.35 |团结报| 55 | 31/12/2014   00:00   IT | 001580/04 | 2 | 00254276 || 200 | 852.3 | 830.3 | 1.35 |团结报| 0 | 31/12/2014   00:00   IT | 001580/05 | 3 | 00305359 || 1700 | 852.3 | 830.3 | 1.35 |团结报| 0 | 31/12/2014   00:00   IT | 001580/06 | 3 | 00305359 || 300 | 852.3 | 830.3 | 1.35 |团结报| 1 | 31/12/2014   00:00

所以我需要:

  1. 阅读文件
  2. 将标题插入table1
  3. 将详细信息插入table2
  4. 对于第一步,我创建一个表,然后使用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 - Header,IT - Details)

    然后,对于我的第二步和第三步,我需要在每个表上插入行,但我还需要分隔每一行的每个字段,因此我创建一个接收字符串和分隔符并返回每个字段的表的过程我的字符串,我动态创建了字段。

    如果要创建该过程,则需要先运行此过程 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
    

    如果你看到我评论执行程序的第三行,你可以得到类似的东西

    我们还没完成,我们读取文件,然后创建返回字段的过程,现在我们需要插入到每个表中,为此我创建了两个带有静态字段的临时表,因为我知道每个字段的字段table然后创建Cursor以读取#ImporData表上的每一行。

    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给我建议分裂。