为什么 SQL Server 2008 R2 在使用批量插入时插入无效的日期时间?

cke*_*rth 5 t-sql sql-server-2008-r2 datetime bulk-insert

我想 在 SQL Server 2008 R2 上使用T-SQL BULK INSERT插入带有可选日期时间值(每行)的行。

一张表可能如下所示:

CREATE TABLE [dbo].[tbl_bulk_insert_datetime_issue] (
    [id] [int] NOT NULL,
    [description] [varchar](20) NOT NULL,
    [datetime] [datetime] NULL,
CONSTRAINT [pk_bulk_insert_datetime_issue] PRIMARY KEY CLUSTERED (
    [id] ASC
))
Run Code Online (Sandbox Code Playgroud)

插入批次:

BULK
INSERT [dbo].[tbl_bulk_insert_datetime_issue]
FROM 'C:\temp\bulkinsertsample.csv'
WITH
(
    FIELDTERMINATOR=';'
)
Run Code Online (Sandbox Code Playgroud)

如果我要插入以下 CSV 内容:

1;row01;
2;row02;20130401
3;row03;
4;row04;20130515
Run Code Online (Sandbox Code Playgroud)

表的内容已按预期解析和插入:

id          description          datetime
----------- -------------------- -----------------------
1           row01                NULL
2           row02                2013-04-01 00:00:00.000
3           row03                NULL
4           row04                2013-05-15 00:00:00.000
Run Code Online (Sandbox Code Playgroud)


但是如果 CSV 文件包含可选日期时间的无效数据

1;row01;
2;row02;20130401
3;row03;not_a_datetime
4;row04;20130515
Run Code Online (Sandbox Code Playgroud)

SQL Server 插入最后一个有效的日期时间值,而不是丢弃带有错误消息的行:

id          description          datetime
----------- -------------------- -----------------------
1           row01                NULL
2           row02                2013-04-01 00:00:00.000
3           row03                2013-04-01 00:00:00.000
4           row04                2013-05-15 00:00:00.000
Run Code Online (Sandbox Code Playgroud)

如果我要插入具有无效日期时间且根本没有有效可解析日期时间的行

1;row01;not_a_datetime
Run Code Online (Sandbox Code Playgroud)

SQL Server会插入该缺省值DATETIME

id          description          datetime
----------- -------------------- -----------------------
1           row01                1900-01-01 00:00:00.000
Run Code Online (Sandbox Code Playgroud)

为什么在使用批量插入时 Sql Server 会插入(对于该特定行)无效的日期时间?
如果我尝试将垃圾插入 INT 列,批量批处理将不会插入该行,并且会引发错误...


更新:
我将分享一些关于我用来重现行为的环境的信息。

  • 操作系统:Windows 7 Enterprise SP1 x64
  • 区域设置:de-DE
  • Microsoft SQL Server 2008 R2 (SP1) - 10.50.2500.0 (X64) 企业版
  • 数据库整理:Latin1_General_100_CS_AS
  • 文件编码:UCS-2 Little Endian(使用Windows CRLF)

正如Max Vernon所暗示的,文件编码似乎有问题。将编码设置为没有 BOM 的 UTF-8 批量插入将抛出我预期的错误并丢弃无效行。

Han*_*non 4

在 SQL Server 2005 和 SQL Server 2012 上,我执行了以下操作:

USE tempdb;
CREATE TABLE ImpTest
(
    ImpTestID INT NULL
    , ImpTestDate DATETIME NULL
);
GO
BULK INSERT ImpTest FROM 'C:\SQLServer\ImportTest.txt' WITH (FIELDTERMINATOR=',');
SELECT * FROM ImpTest;
DROP TABLE ImpTest;
Run Code Online (Sandbox Code Playgroud)

具有以下数据:

1,
2,20130406
3,NOT_DATE
4,
5,20130409
Run Code Online (Sandbox Code Playgroud)

在两台服务器上,我收到以下信息:

Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified
codepage) for row 3, column 2 (ImpTestDate).
Run Code Online (Sandbox Code Playgroud)

也许,正如 Aaron 指出的那样,这是一个需要通过http://connect.microsoft.com解决的错误

我想知道您系统的一些详细信息,包括区域设置、排序规则、导入文件的物理格式(是否来自 Unix 系统?等)。

  • 物理文件是我需要的提示...出于兴趣:我可以在 Sql Server 2005 上重现该行为,文件编码为 UCS-2 Little Endian,排序规则设置为 Latin1_General_CI_AS - 包含无效数据的行插入了错误的日期时间。但是将文件编码设置为 UTF-8 without BOM 会引发我预期的错误,并且未插入该行。 (3认同)