我想将600万行数据插入到我的SQL Server数据库中。我可以用600万INSERT语句来缓慢地进行(根据我的计算,它需要18个小时才能运行)或者我可以尝试BULK INSERT。
BULK INSERT存在无法转义字符的问题,但这种情况下的数据非常简单,所以不应该遇到这个问题。
但是,SQL Server似乎不希望将任何形式的日期/时间数据插入字段中。
这是表(psuedo-SQL)
CREATE TABLE Tasks (
TaskId bigint NOT NULL IDENTITY(1,1) PRIMARY KEY,
TriggerId bigint NOT NULL FOREIGN KEY,
Created datetime NOT NULL,
Modified datetime NOT NULL,
ScheduledFor datetime NULL,
LastRan datetime NULL,
-- and about 10 more fields after this
)
这是我的BULK INSERT声明:
SET DATEFORMAT dmy
BULK INSERT Tasks
FROM 'C:\TasksBulk.dat'
WITH (
-- CHECK_CONSTRAINTS is not necessary as the only constraints are always enforced regardless of this option (UNIQUE, PRIMARY KEY, and NOT NULL)
CODEPAGE = 'RAW',
DATAFILETYPE = 'native',
KEEPIDENTITY,
MAXERRORS = 1,
ORDER ( CallId ASC ),
FIELDTERMINATOR = '\t',
ROWTERMINATOR = '\0'
)
这是TasksBulk.dat中的第一行数据:
1000\t1092\t01/01/2010 04:00:17\t01/01/2010 04:00:17\t\t01/01/2010 04:00:14\0
(为了便于阅读,重新格式化了用4个空格替换的制表符:)
1000 1092 01/01/2010 04:00:17 01/01/2010 04:00:17 01/01/2010 04:00:14\0
然而,当我运行BULK INSERT语句时,我收到此错误:
Msg 4864,Level 16,State 1,Line 2批量加载数据转换错误 (为指定的代码页键入不匹配或无效字符) 第1行第3列(已创建)。
我尝试过使用不同的行和字段终结符以及每种不同的日期/时间格式(包括“01/01/2010”,“2010-01-01”,有和没有“04:00:17”时间零件)。我不知道我在这里做错了什么。
答案 0 :(得分:5)
事实证明,将DATAFILETYPE从'native'更改为'char'解决了这个问题。 'native'类型意味着一切都是严格的数据格式,而'char'意味着更多的纯文本文件。
答案 1 :(得分:1)
您已将CODDEPAGE
设置为RAW
(大概是为了速度)。
错误消息表示您的数据包含代码页之外的字符。
CODEPAGE [ = 'ACP' | 'OEM' | 'RAW' | 'code_page' ]
指定数据文件中数据的代码页。 CODEPAGE是 仅当数据包含char,varchar或text列时才相关 字符值大于127或小于32。
但这可能会误导。您的示例数据行包含缺少的列。如果不使用格式文件,则必须使用表中的每个字段。
因此,您可以为日期时间列创建格式文件或使用varchar(25)创建登台表,导入然后从登台表执行更新到目标表。这样,您就可以更好地控制转化和丢失数据。
答案 2 :(得分:0)
我熟悉的方法是以整数的形式插入日期。
我使用从某个日期开始的秒数(我过去使用10年以上的数据,因为我没有访问任何数据或生成的数据早于此)
日期2012-01-02 12:15:10.000将使用2000年1月1日的参考点存储为378637886。
查询数据库时,可以使用DateAdd(SS,column_name,'2000-01-01')返回列。
如果需要那种精度,你也可以在几毫秒内完成。
我使用自己的自定义函数将我的时间在几秒钟内转换为我想要的任何格式,并且我使用另一个自定义函数将日期转换回秒。
我意识到这可能不是一个好方法,因为它可能需要对您进行数据库更改和代码更改,但也许它可能是其他人认为有用的解决方案概念。