在SQL Server(我正在使用2016)中,有一个名为“大容量插入”的功能,可用于从平面文件插入记录。
当平面文件中的字段为空并且SQL Server中的字段未标记为允许空值时,大容量插入将在插入操作期间静默使用空字符串。
是否有一种方法可以覆盖此行为,所以当字段为null时,它将使用null而不是空字符串。并且因为该字段未设置为null,然后抛出错误?
我为什么要这个?好吧,因为字段默默地插入了一个空字符串值,而我不希望这样做。
注意:我严格是指使用BULK INSERT(不是bcp或任何其他方式)使用T-SQL
注意:我见过Keep Nulls or Use Default Values During Bulk Import (SQL Server),这是我在此文档中找不到的内容。如果您认为它确实包含了我要寻找的内容,请指出我所缺少的,而不是将我定向到该文档。谢谢。
注意:这是一个简单的示例(请注意,这不是我正在使用的表格,只是一个简单的示例,可以用来说明问题)
表定义:
CREATE TABLE [dbo].[TableOne](
[Id] [int] NOT NULL,
[Name] [varchar](10) NOT NULL
)
批量插入命令
BULK
INSERT TableOne
FROM 'R:\TableOne.txt'
WITH(
DATAFILETYPE = 'widechar',
FIELDTERMINATOR = '\t',
ROWTERMINATOR = '\n'
)
文件
1
因此,在此示例中,基本上是:1 [Tab] [CRLF],其中第二列是name,它为空。
结果
答案 0 :(得分:2)
您不能仅通过BULK INSERT
来执行此操作-这种行为是documented,据我所知,没有选择可以更改任何内容:
当导入由
NOT NULL
定义的字符列时 约束,BULK INSERT
在没有值时插入一个空白字符串 在文本文件中。
没有TREAT_BLANK_AS_NULL
选项或类似选项可以帮助解决此问题。
我唯一想到的解决方案是添加约束并在CHECK_CONSTRAINTS
中使用BULK INSERT
。如果您不满意用此约束永久性地标记该列(因为其他情况可能有合法需要插入空值或它们已经存在?),可以暂时添加它:
ALTER TABLE TableOne WITH NOCHECK ADD CONSTRAINT CK_Name_NotEmpty CHECK ([Name] <> '');
BEGIN TRY
BULK INSERT TableOne FROM 'C:\Temp\a.txt' WITH (
DATAFILETYPE = 'widechar',
FIELDTERMINATOR = '\t',
ROWTERMINATOR = '\n',
CHECK_CONSTRAINTS
)
END TRY
BEGIN CATCH
ALTER TABLE TableOne DROP CONSTRAINT CK_Name_NotEmpty;
THROW;
END CATCH
ALTER TABLE TableOne DROP CONSTRAINT CK_Name_NotEmpty;
很显然,如果表是动态的,这会有点不舒服,您需要以这种方式处理许多列,否则您实际上负担不起检查约束。到那时,我建议使用适当的ETL解决方案,例如SSIS软件包。