【问题标题】:BCP/ Bulk Insert Fails (tab delimited file)BCP/批量插入失败(制表符分隔文件)
【发布时间】:2013-12-27 05:21:55
【问题描述】:

我一直在尝试将数据(制表符分隔)导入 SQL 服务器。源数据是从 IBM Cognos 导出的。数据下载地址:sample data

我尝试过 BCP / 批量插入,但没有帮助。原始数据文件包含一个标题行(需要跳过)。

=================================== 架构:

CREATE TABLE [dbo].[DIM_Assessment](
[QueryType] [nvarchar](4000) NULL,
[QueryDate] [nvarchar](4000) NULL,
[APUID] [nvarchar](4000) NULL,
[AssessmentID] [nvarchar](4000) NULL,
[ICDCode] [nvarchar](4000) NULL,
[ICDName] [nvarchar](4000) NULL,
[LoadDate] [nvarchar](4000) NULL
) ON [PRIMARY]
GO

============================== 使用以下命令生成的格式化文件

bcp [dbname].dbo.dim_assessment format nul -c -f C:\config\dim_assessment.Fmt -S <IP>  -U sa -P Pwd

格式文件内容:

11.0
7
1       SQLCHAR             0       8000    "\t"     1     QueryType                    SQL_Latin1_General_CP1_CI_AS
2       SQLCHAR             0       8000    "\t"     2     QueryDate                    SQL_Latin1_General_CP1_CI_AS
3       SQLCHAR             0       8000    "\t"     3     APUID                        SQL_Latin1_General_CP1_CI_AS
4       SQLCHAR             0       8000    "\t"     4     AssessmentID                 SQL_Latin1_General_CP1_CI_AS
5       SQLCHAR             0       8000    "\t"     5     ICDCode                      SQL_Latin1_General_CP1_CI_AS
6       SQLCHAR             0       8000    "\t"     6     ICDName                      SQL_Latin1_General_CP1_CI_AS
7       SQLCHAR             0       8000    "\r\n"   7     LoadDate                     SQL_Latin1_General_CP1_CI_AS

==============================

我尝试使用 BCP / Bulk Insert 导入数据,但是,它们都不起作用。

bcp [dbname].dbo.dim_assessment IN C:\dim_assessment.dat -f C:\config\dim_assessment.Fmt -S <IP>  -U sa -P Pwd

BULK INSERT dim_assessment FROM '\\dbserver\DIM_Assessment.dat'
WITH (
  DATAFILETYPE = 'char',
  FIELDTERMINATOR = '\t',
  ROWTERMINATOR = '\r\n'
);
GO

提前感谢您的帮助@

【问题讨论】:

  • “他们都没有工作”是什么意思?你收到错误信息了吗?如果有,是什么?
  • 是的,目前我无法使用 SSIS 导入数据。我们正在寻找一种将网络上保存的数据导入 SQL 服务器的自动化方法。
  • 我不确定该回复如何回答我的任何问题。
  • @AaronBertrandTes 没有出现错误。除了它说复制了 0 行。
  • 当您尝试 BULK INSERT 时,会发生什么情况?

标签: sql sql-server bulkinsert bcp csv


【解决方案1】:

您的输入文件格式很糟糕。

您的格式文件和您的BULK INSERT 命令都声明一行的结尾应该是回车和换行的组合,并且有七列数据。但是,如果您在记事本中打开 CSV 文件,您会很快看到在 Windows 中没有正确观察到回车和换行(这意味着它们必须不是精确的 \r\n)。您还可以看到,实际上并不是七列数据,而是五列:

QueryType   QueryDate   APUID   AssessmentID    ICDCode ICDName LoadDate
PPIC    2013-11-20 10:23:14 11431   10963       Tremors
PPIC    2013-11-20 10:23:14 11431   11299       THUMB PAIN
PPIC    2013-11-20 10:23:14 11431   11348       Environmental allergies
...

Just looking at it visually you can tell it isn't right,你需要得到一个更好的源文件,然后才能把它扔到 SQL Server 的墙上并期望它能够顺利处理它:

【讨论】:

  • 我不知道该说什么。可能正如其他人所解释的那样,某些列丢失/空白,这就是您看到这种错误格式的数据文件的原因?
【解决方案2】:

刚刚将您的文件保存为 .CSV 并使用以下语句批量插入。

BULK INSERT dim_assessment FROM 'C:\Blabla\TestFile.csv'
WITH (
  FIRSTROW = 2,
  FIELDTERMINATOR = ',',
  ROWTERMINATOR = '\n'
);
GO

返回消息

(22587 row(s) affected)

加载的数据

请注意,ICD 名称中的一些数据已溢出到 LoadDate 列,只需使用| 管道字符来分隔并使用与FIELDTERMINATOR = '|' 相同的批量插入语句和快乐的日子。

【讨论】:

  • 添加分隔符(管道)可能不可行。
  • 您是否知道一种方法可以从命令行使用“管道”或不需要手动干预的方式保存此制表符分隔文件?
  • 该文件已被标记为“.csv”,但采用制表符分隔的格式。您的意思是您在 Excel 中手动打开它,然后将其重新保存为 CSV?不幸的是,您不能每次都手动执行此操作。真正的解决方法是首先获得正确的输出,因此您不必在两者之间执行手动步骤...
  • @AaronBertrand... 所以,我将数据保存为管道分隔符(全部以编程方式)。到目前为止,我在通过 bcp 保存数据时遇到了问题。我在尝试发出 bcp 时收到以下错误:Starting copy... SQLState = S1000, NativeError = 0 Error = [Microsoft][SQL Server Native Client 11.0]Unexpected EOF encountered in BCP data-file 21 rows copied. Network packet size (bytes): 4096 Clock Time (ms.) Total : 78 Average : (269.23 rows per sec.)
  • 它说复制了 21 行,但是,除了第一行,第一列之外的所有行都有一些垃圾值。我不知道这里发生了什么。这是一个简单的 BCP 输入,指定了管道分隔符。
【解决方案3】:

通过 Excel 打开文件显示如下:

  • 确实有7行标题
  • 只有前六个被填充
  • 第 1、2 和 3 列的值相同
  • 有一些令人困惑的数据,其中第五列可以是空的,也可以是用数字填充的,也可以是用文本填充的。

我猜,在这些情况下,批量插入可能无法正常工作。由于 Excel 似乎以非常干净的方式管理您的文件,您应该考虑一个额外的步骤,从 CSV 到 Excel,然后到您的数据库。

【讨论】:

  • 哇,我很高兴看到这个。当您说应该有一个额外的步骤时,有没有办法将制表符分隔文件保存为 excel 中的“逗号”分隔文件,然后从命令行导入数据?如果发生这种情况,我就是金子!
  • 您应该通过 Excel 的“另存为”选项尝试一下。如果您可以手动完成,则意味着有一种方法可以以编程方式完成。普通的 T-SQL 可能无法解决问题,但肯定有一些命令行软件可用。谷歌一下就行了。
  • 我正在搜索!当我找到东西时,会在这里发布。谢谢
  • 好的,所以我可以使用 vba 将文件保存为“csv”。当我使用批量导入导入文件时,它会被导入服务器。但是,有一个小问题。文件中的数据(在记事本中打开时)显示:PPIC,11/20/2013 10:23,11431,10963,,Tremors ,PPIC,11/20/2013 10:23,11431,11592,,"Glioblastoma, Barin ", 第一行已正确插入。第二行插入,但是,最后一列被保存到多列中(我相信这是因为额外的逗号)我该如何解决这个问题?
  • 如果您使用 VBA,那么我建议您直接使用 Excel 对象和工具并将文件另存为 XLS(或尝试 XML?)。这将避免这种昏迷问题。然后,您可以继续使用 VBA 并根据您的 XLS 文件打开记录集,或者通过 SQL Server 切换到导入过程。
【解决方案4】:

好的,因此,将分隔数据从平面文件推送到 SQL Server 是一项看似简单的任务。我认为 BCP 是要走的路(我之前用过,而且很成功)。

对建议的简要说明: 一种。修复源文件 湾。以原生 excel 格式保存源数据 C。将源数据保存为管道分隔数据

我尝试了所有选项,但它在我的流程中添加了多个步骤,但可行。

我偶然发现了来自 powershell 的 invoke-sqlcmd 和 import-csv 命令行开关。原来,我可以直接使用 powershell 导入数据。目前它有点慢,但是,我现在可以忍受。

$DATA=IMPORT-CSV dim_assessment.CSV -Delimiter "`t"

FOREACH ($LINE in $DATA)

{
$QueryType="`'"+$Line.QueryType+"`'"
$QueryDate="`'"+$Line.QueryDate+"`'"
$APUID="`'"+$Line.APUID+"`'"
$AssessmentID="`'"+$Line.AssessmentID+"`'"
$ICDCode="`'"+$Line.ICDCode+"`'"
    $ICDName=$Line.ICDName
    $ICDName = $ICDName.replace("'","''")
$ICDName="`'"+$ICDName+"`'" 
$LoadDate="`'"+$Line.LoadDate+"`'"

$SQLHEADER="INSERT INTO [dim_assessment] ([QueryType],[QueryDate],[APUID],[AssessmentID],[ICDCode],[ICDName],[LoadDate])"
$SQLVALUES="VALUES ($QueryType,$QueryDate,$APUID,$AssessmentID,$ICDCode,$ICDName,$LoadDate)"

$SQLQUERY=$SQLHEADER+$SQLVALUES
Invoke-Sqlcmd –Query $SQLQuery -ServerInstance HA -U sa -P Pwd

}

感谢您的帮助!

【讨论】:

    猜你喜欢
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 2017-08-23
    • 1970-01-01
    相关资源
    最近更新 更多