批量插入CSV文件中的不同列号

时间:2013-08-14 16:08:18

标签: sql sql-server sql-server-2000 bulkinsert

我正在尝试使用BULK INSERT将CSV文件中的数据导入表格。以下是我的工作存储过程来完成此任务:

USE [Database]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[delete_fill]
    AS

    TRUNCATE TABLE dataImport

    BULK
    INSERT dataImport
    FROM 'c:\fileshare\temp.CSV'
    WITH
    (
    FIRSTROW = 2,
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n'
    )

    SELECT * FROM dataImport ORDER BY StoreID, ItemID
    RETURN

现在我可能在CSV文件中添加了2个新列。如何修改我的存储过程,以便在接受只有三列的文件时考虑两个新列,在数据库中将两个新列保留为空。

只需向表dataImport添加两列并运行该过程不起作用。我收到此错误:“消息4864,级别16,状态1,过程delete_fill,第7行 第2行第3列(价格)的批量加载数据转换错误(类型不匹配或指定代码页的无效字符)。“

dataImport结构和请求的csv数据示例:

Create table dataImport(
StoreID BIGINT not null,
ItemID BIGINT not null,
Price money not null,
TwoforQuantity Int,
TwoforPrice money
)

3列:

StoreID, ItemID, Price
133,51425,11.79
133,80277,1.49
133,15544,5.28

5列:

StoreID, ItemID, Price, IntField, MoneyField
133,51425,11.79,2,20.99
133,80277,1.49,2,2.00
133,15544,5.29,3,14.99

2 个答案:

答案 0 :(得分:1)

我前段时间遇到了类似的问题。以下是我们如何解决它的概述:

  • 数据文件包含X个列,其中列实际上是随机顺序
  • 第一行列出了包含数据的行
  • 表包含Y列。除了主键列之外,不能假设哪个列在哪个列中

解决方案:

  • BULK将第一行仅作为单个列(无列分隔符)插入varchar(max)
  • 解析它,识别文件
  • 中的列(和顺序!)
  • 根据需要向表中添加列(ATLER TABLE)。当我们用完列时很大的问题,但这是另一个故事。
  • 在表格上创建一个视图,仅列出当前列,根据文件排序但“映射”到表格中的正确列
  • 不在视图中的列默认为NULL。 (或者,如果不可为空,则必须设置默认约束)
  • 是的,我们使用了很多动态SQL
  • BULK INSERT行2及以上的视图

您可能需要编写大量基础设施来管理所有这些。每次运行:   - 如果存在视图,请将其删除   - 如果存在“加载默认值”,则删除它们   - 按上述步骤进行

(为了调试目的,我留下了“最后一轮”的观点和内容。)

答案 1 :(得分:0)

如果文件中的列号是固定的(3或5),而表有5列,那么 -

  1. 查找文件中的列总数 - 您可以使用不同的方法。要么在上传文件之前找到它,要么只在BULK INSERT第一行找到它并计算它。
  2. 根据列数创建临时表
  3. 然后`BULK INSERT'到临时表。
  4. 最后,您可以将临时表中的数据插入主表。
  5. 您需要使用动态查询。

    您的查询看起来像 -

    DECLARE @sql VARCHAR(8000) 
    DECLARE @column_number INT
    SET @column_number = 5 -- OR 3
    
    IF @column_number = 3
    BEGIN
        SET @sql = ' 
                create table #tmp (
                    StoreID varchar(100),
                    ItemID varchar(100),
                    Price varchar(100)
                );'
    END
    ELSE
    BEGIN
        SET @sql = ' 
                create table #tmp (
                    StoreID varchar(100),
                    ItemID varchar(100),
                    Price varchar(100),
                    IntField varchar(100),
                    MoneyField varchar(100)
                );'
    END
    
    SET @sql = @sql + ' BULK INSERT #tmp
                        FROM ''c:\fileshare\temp.CSV''
                        WITH
                        (
                        FIRSTROW = 2,
                        FIELDTERMINATOR = '','',
                        ROWTERMINATOR = ''\n''
                        )'
    
    SET @sql = @sql + ' IF ' + CAST(@column_number AS VARCHAR(10)) + ' = 3
                        BEGIN
                            INSERT INTO dataImport (StoreID, ItemID, Price)
                            SELECT StoreID, ItemID, Price FROM #tmp
                        END
                        ELSE IF ' + CAST(@column_number AS VARCHAR(10)) + ' = 5
                        BEGIN
                            INSERT INTO dataImport (StoreID, ItemID, Price, IntField, MoneyField)
                            SELECT StoreID, ItemID, Price, IntField, MoneyField FROM #tmp
                        END'
    EXEC(@sql)