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(默认值)而不是“,”?
没有数据文件第一行中的列名,或者文件中每个位置的值,或者数据文件中所有行变体的完整样本,必须假设:
- 行终止符还应包括字段终止符,或者
- 数据源中有一个未知的附加列未在 table 中说明。
可能不太常见,但字段终止符也包含在行终止符中的情况并不少见。事实上,许多 examples on MSDN for bulk insert
将 fieldterminator
显示为 rowterminator
的前导部分。
此解决方案假定 rowterminator
是 fieldterminator
的一部分,类似于 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 服务器打算保持灵活性或选择不丢失孤立数据,但造成的混乱多于帮助。
我正在尝试使用 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(默认值)而不是“,”?
没有数据文件第一行中的列名,或者文件中每个位置的值,或者数据文件中所有行变体的完整样本,必须假设:
- 行终止符还应包括字段终止符,或者
- 数据源中有一个未知的附加列未在 table 中说明。
可能不太常见,但字段终止符也包含在行终止符中的情况并不少见。事实上,许多 examples on MSDN for bulk insert
将 fieldterminator
显示为 rowterminator
的前导部分。
此解决方案假定 rowterminator
是 fieldterminator
的一部分,类似于 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 服务器打算保持灵活性或选择不丢失孤立数据,但造成的混乱多于帮助。