带有标识(自动增量)列的BULK INSERT

时间:2012-06-01 13:18:07

标签: sql-server bulkinsert identity-column

我正在尝试从CSV文件中添加数据库中的批量数据。

员工表有一列ID(PK)自动递增。

CREATE TABLE [dbo].[Employee](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [Name] [varchar](50) NULL,
 [Address] [varchar](50) NULL
) ON [PRIMARY]

我正在使用此查询:

BULK INSERT Employee  FROM 'path\tempFile.csv ' 
WITH (FIRSTROW = 2,KEEPIDENTITY,FIELDTERMINATOR = ',' , ROWTERMINATOR = '\n');

.CSV文件 -

Name,Address
name1,addr test 1
name2,addr test 2

但会导致出现此错误消息:

  

第2行第1列(id)的批量加载数据转换错误(指定代码页的类型不匹配或无效字符)。

9 个答案:

答案 0 :(得分:94)

将id列添加到csv文件中并将其留空:

id,Name,Address
,name1,addr test 1
,name2,addr test 2

从查询中删除KEEPIDENTITY关键字:

BULK INSERT Employee  FROM 'path\tempFile.csv ' 
WITH (FIRSTROW = 2,FIELDTERMINATOR = ',' , ROWTERMINATOR = '\n');

id identity字段将自动递增。

如果您为csv中的id字段指定值,除非您使用KEEPIDENTITY关键字,否则它们将被忽略,然后它们将被用来代替自动增量。

答案 1 :(得分:39)

不要直接插入您的真实表格。

我会永远

  1. 从CSV文件中插入暂存dbo.Employee_Staging(不包含IDENTITY列)
  2. 可能编辑/清理/操纵您导入的数据
  3. 然后使用T-SQL语句将数据复制到实际表中,如:

    INSERT INTO dbo.Employee(Name, Address) 
       SELECT Name, Address
       FROM dbo.Employee_Staging
    

答案 2 :(得分:24)

我有类似的问题,但我需要确保ID的顺序与源文件中的顺序对齐。 我的解决方案是使用VIEW进行BULK INSERT:

保持你的桌子不变并创建这个VIEW(选择ID栏以外的所有内容)

CREATE VIEW [dbo].[VW_Employee]
AS
SELECT [Name], [Address]
FROM [dbo].[Employee];

您的BULK INSERT应如下所示:

BULK INSERT [dbo].[VW_Employee] FROM 'path\tempFile.csv ' 
WITH (FIRSTROW = 2,FIELDTERMINATOR = ',' , ROWTERMINATOR = '\n');

答案 3 :(得分:7)

您必须使用格式文件进行批量插入:

   BULK INSERT Employee FROM 'path\tempFile.csv ' 
   WITH (FORMATFILE = 'path\tempFile.fmt');

格式文件(tempFile.fmt)如下所示:

  

11.0
2
1 SQLCHAR 0 50“\ t”2名称SQL_Latin1_General_CP1_CI_AS
  2 SQLCHAR 0 50 “\ r \ n” 个3个地址SQL_Latin1_General_CP1_CI_AS

此处有更多详情 - http://msdn.microsoft.com/en-us/library/ms179250.aspx

答案 4 :(得分:2)

我的解决方案是将ID字段添加为表中的LAST字段,因此批量插入会忽略它并获得自动值。干净简单......

例如,如果插入临时表:

CREATE TABLE #TempTable 
(field1 varchar(max), field2 varchar(max), ... 
ROW_ID int IDENTITY(1,1) NOT NULL)

请注意,ROW_ID字段必须始终指定为最后一个字段!

答案 5 :(得分:0)

另一个选项,如果您使用的是临时表而不是临时表,则可以按导入所需的方式创建临时表,然后在导入后添加标识列。

所以你的sql做了这样的事情:

  1. 如果临时表存在,请删除
  2. 创建临时表
  3. 批量导入临时表
  4. 更改临时表添加标识
  5. <无论你想做什么数据>
  6. 放下临时表
  7. 仍然不是很干净,但这是另一种选择......可能也必须让锁具安全。

答案 6 :(得分:0)

我有同样的问题导致损失时间,所以我鼓励分享我的调查结果和解决方案。

<强> 1。使用Excel文件

这是我采用的方法。我没有使用csv文件,而是使用了excel文件(.xlsx),内容如下所示。

id  username   email                token website

    johndoe   johndoe@divostar.com        divostar.com
    bobstone  bobstone@divosays.com        divosays.com

请注意,id列没有值。

接下来,使用Microsoft SQL Server Management Studio连接到您的数据库,右键单击您的数据库并选择导入数据(任务下的子菜单)。选择Microsoft Excel作为源。当您到达名为&#34;选择源表和视图&#34;的阶段时,单击编辑映射。对于目标下的id列,请点击它,然后选择忽略。不要检查Enable Identity insert,除非您想要在其他数据库中导入数据并且希望维护源数据库的自动增量ID。继续完成,那就是它。您的数据将顺利导入。

<强> 2。使用CSV文件

在您的csv文件中,请确保您的数据如下所示。

id,username,email,token,website
,johndoe,johndoe@divostar.com,,divostar.com
,bobstone,bobstone@divosays.com,,divosays.com

运行以下查询:

BULK INSERT Metrics FROM 'D:\Data Management\Data\CSV2\Production Data 2004 - 2016.csv '
WITH (FIRSTROW = 2, FIELDTERMINATOR = ',', ROWTERMINATOR = '\n');

这种方法的问题是CSV应该在DB服务器或DB可以访问的某个共享文件夹中,否则您可能会收到错误,例如&#34;无法打开文件。操作系统返回错误代码21(设备尚未就绪)&#34;。

如果要连接到远程数据库,则可以将CSV上载到该服务器上的目录,并引用批量插入的路径。

第3。使用CSV文件和Microsoft SQL Server Management Studio导入选项

像第一种方法一样启动导入数据。对于来源,请选择平面文件来源并浏览您的CSV文件。确保右侧菜单(常规,列,高级,预览)正常。确保在列菜单(列分隔符)下设置正确的分隔符。就像上面的excel方法一样,单击编辑映射。对于目标下的ID列,请点击它,然后选择忽略

继续完成,就是这样。您的数据将顺利导入。

答案 7 :(得分:0)

  1. 使用“身份”列+其他列创建表;
  2. 在该视图上创建一个视图,并仅显示要批量插入的列;
  3. 视图中的BCP

答案 8 :(得分:0)

这是一个很老的答案,但是给出的答案都不能在不改变条件的情况下解决问题,这是我做不到的。

我通过使用BULK INSERT的OPENROWSET变体解决了它。它使用相同的格式文件并以相同的方式工作,但是它允许使用SELECT语句读取数据文件。

创建表格:

CREATE TABLE target_table(
id bigint IDENTITY(1,1),
col1 varchar(256) NULL,
col2 varchar(256) NULL,
col3 varchar(256) NULL)

打开命令窗口运行:

bcp dbname.dbo.target_table format nul -c -x -f C:\format_file.xml -t; -T

这会根据表格的外观创建格式文件。

现在,编辑格式文件,并删除FIELD ID =“ 1”和COLUMN SOURCE =“ 1”的所有行,因为我们的数据文件中不存在此行。
还要根据数据文件的需要调整终止符:

<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RECORD>
  <FIELD ID="2" xsi:type="CharTerm" TERMINATOR=";" MAX_LENGTH="256" COLLATION="Finnish_Swedish_CI_AS"/>
  <FIELD ID="3" xsi:type="CharTerm" TERMINATOR=";" MAX_LENGTH="256" COLLATION="Finnish_Swedish_CI_AS"/>
  <FIELD ID="4" xsi:type="CharTerm" TERMINATOR="\r\n" MAX_LENGTH="256" COLLATION="Finnish_Swedish_CI_AS"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="2" NAME="col1" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="3" NAME="col2" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="4" NAME="col3" xsi:type="SQLVARYCHAR"/>
 </ROW>
</BCPFORMAT>

现在,我们可以通过选择将数据文件批量加载到表中,从而完全控制列,在这种情况下,无需将数据插入标识列:

INSERT INTO target_table (col1,col2, col3)
SELECT * FROM  openrowset(
bulk 'C:\data_file.txt',
formatfile='C:\format_file.xml') as t;