【问题标题】:Bulk Insert Varying Column Numbers in CSV File在 CSV 文件中批量插入不同的列号
【发布时间】:2013-08-14 16:08:18
【问题描述】:

我正在尝试使用 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

【问题讨论】:

  • 阅读这个,同样的情况stackoverflow.com/questions/2601941/…
  • 对不起,最初应该包含它:Msg 4864, Level 16, State 1, Procedure delete_fill, Line 7 Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 2,第 3 列(价格)
  • 谢谢,我已经阅读了,但情况并非如此。我的列在文件中不会有所不同。该文件将有 3 列或 5 列。希望有比上述更好的解决方案。
  • 我决定执行以下操作:我正在从 VB.Net 应用程序启动存储过程,因此我将在上传到服务器之前检查文件中的列数。然后我将向 SP 添加一个参数,它是文件中的列数(它始终是 3 或 5)。将两张表添加到数据库 - 一张有 3 列,一张有 5 列。根据列参数,我将填充并返回不同的表。如果有人有更优雅的解决方案,请告诉我。 :D
  • 你能从你的dataImport的文件和表结构中发布示例数据吗?

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


【解决方案1】:

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

  • 数据文件包含 X 列,其中列实际上是随机顺序的
  • 第一行列出了列,接下来的行包含数据
  • 表包含 Y 列。除非主键列,否则无法假设哪些列在哪个集合中

解决方案:

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

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

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

【讨论】:

    【解决方案2】:

    如果文件中的列数是固定的(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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-21
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多