BULK INSERT 插入定界符而不是空字段的默认 NULL 值

BULK INSERT inserts delimiter instead of default NULL value for empy field

我正在尝试使用 BULK INSERT 插入一些行:

CREATE TABLE Foo (
  Id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT newsequentialid(),
  Name NVARCHAR(255) NULL,
  CreatedOn DATETIME NOT NULL DEFAULT GETDATE(),
  CreatedBy NVARCHAR(255) NOT NULL DEFAULT SUSER_NAME(),
  ModifiedOn DATETIME NULL DEFAULT NULL,
  ModifiedBy NVARCHAR(255) NULL DEFAULT NULL
);

我从 CSV 文件中插入,该文件采用 UTF8 编码,逗号用于分隔符,LF 用于行尾:

 ,Fizz,,,,,

我的 BULK INSERT 语句如下所示:

BULK INSERT Foo 
FROM 'C:\foo.csv' 
WITH (CODEPAGE = '65001', FIELDTERMINATOR = ',' , ROWTERMINATOR = '0x0a');

但插入行 (ModifiedBy) 的最后一个字段的值为 ','(逗号分隔符:

49625A3B-DCF1-E611-8D73-B00594F7CD91    Fizz    2017-02-13 12:04:48.223 sa  NULL    ,

我做错了什么以及如何让 BULK INSERT 将最终字段插入为 NULL(默认值)而不是“,”?

没有数据文件第一行中的列名,或者文件中每个位置的值,或者数据文件中所有行变体的完整样本,必须假设:

  1. 行终止符还应包括字段终止符,或者
  2. 数据源中有一个未知的附加列未在 table 中说明。

可能不太常见,但字段终止符也包含在行终止符中的情况并不少见。事实上,许多 examples on MSDN for bulk insertfieldterminator 显示为 rowterminator 的前导部分。

此解决方案假定 rowterminatorfieldterminator 的一部分,类似于 MSDN 上的示例:

bulk insert Foo 
from 'C:\foo.csv' 
with (
    codepage = '65001'
  , fieldterminator = ',' 
  , rowterminator = '0x2c0a'
  );

只数逗号...

Foo table 有 6 列,而给定的输入有 7 个位置。

假定最后一个逗号是 ModifiedBy 列的值。

Id,NAME,CreatedOn,CreatedBy,ModifiedOn,ModifiedBy,?

带有七个逗号的输入 ,Fizz,,,,,, 将为 ModifiedBy.

呈现 ,,

我想,你的选择不多了。

i) 更改批量插入方法,改为使用 OPENROWSET 或 OPENQUERY.IT 允许您提及列 name.Example link、

https://www.mssqltips.com/sqlservertip/1207/different-options-for-importing-data-into-sql-server/

ii) 如果 i) 不接受table,那么您可以在 table 上定义 "After insert" 触发器,您可以在其中再次将 modifiedDate 更新为 null。

我认为解决方案一是完美的。

table 的最后一列在分配其他列后接收输入行中的所有剩余数据,显然没有进行过解析。如果在输入行中放置 100 个逗号,那么在导入的 table 的最后一列中将得到 95 个逗号(我通过快速测试验证了这一点)。正如 Marcus 还指出的那样,6 列布局必须有 5 个分隔符。

如果您无法从输入文件中删除额外的字段,您可以使用格式文件进行列映射,以排除在以下内容中解释的最后一列:https://msdn.microsoft.com/en-us/library/ms187908.aspx

如果您的输入文件确实是为 6 列设计的,并且按照惯例最后一个分隔符在那里,即 "there is a delimiter after each column" 而不是 "delimiters between columns",那么@SqlZim 的解决方案大多数情况下应该可以正常工作。但是话又说回来,您必须确保在一行中的最后一个定界符之后没有添加 white-space 等(例如手动编辑时),否则该行的导入将失败,因为它与该行不匹配分隔符。因此,为了更简单,我再次建议使用列映射方法,为最后一个分隔符添加一个虚拟字段定义并在导入期间跳过它。

看起来 Sql 服务器打算保持灵活性或选择不丢失孤立数据,但造成的混乱多于帮助。