1

我正在尝试使用 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 添加两列并运行该过程是行不通的。我收到此错误:“第 2 行第 3 列(价格)的消息 4864,级别 16,状态 1,过程 delete_fill,第 7 行批量加载数据转换错误(指定代码页的类型不匹配或无效字符)。”

根据要求的 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
4

2 回答 2

1

不久前我遇到了类似的问题。以下是我们如何解决它的粗略概述:

  • 数据文件包含 X 列,其中列有效地以随机顺序排列
  • 第一行列出了列,后面的行包含数据
  • 表包含 Y 列。除非主键列,否则无法假设哪些列在哪个集合中

解决方案:

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

您可能必须编写大量基础架构来管理所有这些。对于每次运行: - 如果存在视图,则删除它 - 如果存在“加载默认值”,则删除它们 - 如上所述继续

(出于调试目的,我保留了“最后一轮”视图和内容。)

于 2013-08-14T16:39:10.620 回答
0

如果文件中的列数是固定的(3 或 5)并且表有 5 列,则 -

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

您需要使用动态查询。

您的查询将类似于 -

声明@sql VARCHAR(8000)
声明 @column_number INT
SET @column_number = 5 -- 或 3

如果@column_number = 3
开始
    设置@sql = '
            创建表 #tmp (
                StoreID varchar(100),
                ItemID varchar(100),
                价格 varchar(100)
            );'
结尾
别的
开始
    设置@sql = '
            创建表 #tmp (
                StoreID varchar(100),
                ItemID varchar(100),
                价格 varchar(100),
                IntField varchar(100),
                MoneyField varchar(100)
            );'
结尾

SET @sql = @sql + ' 批量插入 #tmp
                    FROM ''c:\fileshare\temp.CSV''
                    和
                    (
                    第一次 = 2,
                    FIELDTERMINATOR = '','',
                    ROWTERMINATOR = ''\n''
                    )'

SET @sql = @sql + ' IF ' + CAST(@column_number AS VARCHAR(10)) + ' = 3
                    开始
                        INSERT INTO dataImport (StoreID, ItemID, Price)
                        从#tmp 中选择 StoreID、ItemID、价格
                    结尾
                    ELSE IF ' + CAST(@column_number AS VARCHAR(10)) + ' = 5
                    开始
                        插入数据导入(StoreID、ItemID、Price、IntField、MoneyField)
                        从#tmp 中选择 StoreID、ItemID、价格、IntField、MoneyField
                    结尾'
执行(@sql)
于 2013-08-14T17:12:58.963 回答