65.9K
CodeProject 正在变化。 阅读更多。
Home

将数据从文本或 CSV 文件导入 SQL Server

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2011年11月26日

CPOL

2分钟阅读

viewsIcon

439845

将数据从文本或 CSV 文件导入 SQL Server

我最近需要将 CSV(逗号分隔文件)中的数据导入到 SQL Server 2008 中的一个表。
在 Google 上搜索了一段时间后,我找到了 Pinal Dave (SQL Authority) 的这篇博文,他总是提供高质量的内容。

除了分享 Pinal 博客文章中描述的技术之外,我还想通过解释我遇到的一些问题来扩展一下。

我的 CSV 文件中的源数据看起来像这样

HOU009,Windows Phone 7,Will Martinez,
11/10/2011,Houston; TX,999,2
HOU010,WPF for Business Applications,Will Martinez,
11/15/2011,Houston; TX,695,1

大致来说,我拥有填充目标表所有列所需的所有数据。我的假设是我的 `uniqueidentifier` 类型的 id 列将自动生成。这是我的表

CREATE TABLE [dbo].[Courses](
   [id] [uniqueidentifier] NOT NULL DEFAULT NEWSEQUENTIALID(),
   [code] [varchar](50) NOT NULL,
   [description] [varchar](200) NULL,
   [instructor] [varchar](50) NULL,
   [date] [date] NULL,
       [venue] [varchar](50) NULL,
   [price] [money] NULL,
       [duration] [int] NULL,
 CONSTRAINT [PK_Courses] 
    PRIMARY KEY CLUSTERED ([id] ASC,[code] ASC )
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, _
	IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
  ON [PRIMARY]) ON [PRIMARY]

正如你可能注意到的,我有两种数据类型可能具有挑战性,首先我的主键是 `uniqueidentifier` 类型,而且,我正在使用 `date` 数据类型。

最初,我尝试使用以下语句从 CSV 文件导入我的数据

bulk insert [dbo].[Courses]
from 'C:\Courses.csv'
with (fieldterminator = ',', rowterminator = '\n')
go

我第一次尝试没有成功。我遇到了以下问题

Msg 4861, Level 16, State 1, Line 1
Cannot bulk load because the file "C:\Courses.csv" 
could not be opened. Operating system error code 5
(Access is denied.).

将我的文件移动到 *Public* 目录,然后确保权限设置为 'Everyone'。仍然没有成功,虽然我没有收到“访问被拒绝”的错误。我的插入返回 0 行受影响。

此时,我的猜测是我遇到了两个问题

  • 首先,我没有为 Id 列(我们的主键)提供值
  • 如果存在 `string` 数据的隐式转换,我的 `date` 类型的列可能会有问题

为了解决这个问题,我决定创建一个新的临时表,没有主键,并且有一个 `datetime` 数据字段。这是表

CREATE TABLE [dbo].[CoursesTemp](
   [code] [varchar](50) NOT NULL,
   [description] [varchar](200) NULL,
   [instructor] [varchar](50) NULL,
   [date] [datetime] NULL,
   [venue] [varchar](50) NULL,
   [price] [money] NULL,
   [duration] [int] NULL)

再次运行我的 `insert` 语句

bulk insert [dbo].[CoursesTemp]
from 'C:\Users\Public\Downloads\Courses.csv'
with (fieldterminator = ',', rowterminator = '\n')
go

成功!终于看到了我等待的结果...(20 行受影响)。

此时,一切都很容易。我可以使用刚刚插入到临时表中的数据,并将其用于插入到“live”表中。

insert [dbo].[Courses]
  (code, description, instructor, date, venue, duration)
select 
   code, description, instructor, cast(date as date), venue,
   duration
from [dbo].[CoursesTemp]

请注意,我的 Id 列未列出,因为它具有一个默认值为 NEWSEQUENTIALID 的 `uniqueidentifier`,它会自动为每条记录生成一个 `GUID`。

为了解决日期字段的问题,我注意到有一个 CAST 语句可以将数据转换为适当的 `datatype`。

以下是我的表中数据的样子

?

现在,我拥有我需要的数据,并且我的 id 列为每条记录生成了漂亮的 `GUID`。
我已经准备好开始工作了。

希望这能帮助到有人,
Will

© . All rights reserved.