《PowerShell V3——SQL Server 2012数据库自动化运维权威指南》——2.21 使用bcp实施批量导入

本节书摘来自异步社区出版社《PowerShell V3—SQL Server 2012数据库自动化运维权威指南》一书中的第2章,第2.21节,作者:【加拿大】Donabel Santos,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.21 使用bcp实施批量导入

本方案描述了如何用PowerShell和bcp将CSV文件导入SQL Server。

2.21.1 准备

为了测试导入,首先创建一个类似于AdventureWorks2008R2数据库的Person.Person表Person,简单修改下。我们创建Test架构,并移除一些约束,保持该表尽可能简单和独立。

如果Test.Person不存在你的环境中,让我们创建它。打开SSMS,运行如下代码。

CREATE SCHEMA [Test]
GO
CREATE TABLE [Test].[Person](
 [BusinessEntityID] [int] NOT NULL PRIMARY KEY,
 [PersonType] [nchar](2) NOT NULL,
 [NameStyle] [dbo].[NameStyle] NOT NULL,
 [Title] [nvarchar](8) NULL,
 [FirstName] [dbo].[Name] NOT NULL,
 [MiddleName] [dbo].[Name] NULL,
 [LastName] [dbo].[Name] NOT NULL,
 [Suffix] [nvarchar](10) NULL,
 [EmailPromotion] [int] NOT NULL,
 [AdditionalContactInfo] [xml] NULL,
 [Demographics] [xml] NULL,
 [rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
 [ModifiedDate] [datetime] NOT NULL
)
GO

2.21.2 如何做…

1.通过“Start | Accessories | Windows PowerShell | Windows PowerShell ISE”打开PowerShell控制台。

2.首先添加一些辅助函数。输入如下并执行。

Import-Module SQLPS -DisableNameChecking
$instanceName = "KERRIGAN"
$dbName = "AdventureWorks2008R2"
function Truncate-Table {
<# 
.SYNOPSIS 
   Very simple function to truncate 
   records from Test.Person 
.NOTES 
   Author   : Donabel Santos 
.LINK 
   http://www.sqlmusings.com
#>
param([string]$instanceName,[string]$dbName)
$query = @"
TRUNCATE TABLE Test.Person
"@
#check number of records
Invoke-Sqlcmd -Query $query `
-ServerInstance $instanceName `
-Database $dbName
}
function Get-PersonCount {
<# 
.SYNOPSIS 
   Very simple function to get number 
   of records in Test.Person 
.NOTES 
   Author   : Donabel Santos 
.LINK 
   http://www.sqlmusings.com
#> 
param([string]$instanceName,[string]$dbName)
$query = @"
SELECT COUNT(*) AS NumRecords
FROM Test.Person
"@
#check number of records
Invoke-Sqlcmd -Query $query `
-ServerInstance $instanceName `
-Database $dbName
}

3.添加如下脚本并运行。

#let's clean up the Test.Person table first
Truncate-Table $instanceName $dbName
$server = "KERRIGAN"
$table = "AdventureWorks2008R2.Test.Person"
$importfile = "C:\Temp\Exports\AdventureWorks2008R2.Person.Person.csv"
#command to import from csv
$cmdimport = "bcp $($table) in `"$($importfile)`" -S$server -T -c -t `"|`" -r `"\n`" " 
<#
$cmdimport gives you something like this:
bcp AdventureWorks2008R2.Test.Person in
"C:\Temp\Exports\AdventureWorks2008R2.Person.Person.csv" -SKERRIGAN -T -c -t "|" -r 
"\n" 
#>
#run the import command
Invoke-Expression $cmdimport 
#delay 1 sec, give server some time to import records
#sleep helps us avoid race conditions
Start-Sleep -s 2
Get-PersonCount $instanceName $dbName

2.21.3 如何实现…

使用bcp实施批量导入是一个直接的任务——我们需要使用Invoke-Expression cmdlet并传入bcp命令。然而,在本方案中,我们整理了脚本,并以一对辅助函数开头。

第一个辅助函数Truncate-Table,是一个简单的用于清空Test.Person表的辅助函数,该表用于导入记录。该函数通过使用Invoke-Sqlcmd cmdlet将TRUNCATE TABLE命令传递给SQL Server。使用该函数时,只需调用。

Truncate-Table $instanceName $dbName

第二个辅助函数Get-PersonCount,只需返回导入到Test.Person表的记录行数。这也使用了Invoke-Sqlcmd cmdlet。调用该函数时,使用如下代码。

Get-PersonCount $instanceName $dbName

本方案的核心是根据创建的bcp导入命令。

$server = "KERRIGAN"
$table = "AdventureWorks2008R2.Test.Person"
$importfile = "C:\Temp\Exports\AdventureWorks2008R2.Person.Person.csv"
#command to import from csv
$cmdimport = "bcp " + $table + " in " + '"' + $importfile + '"' + " -S $server
-T -c -t `"|`" -r `"\n`" "

该bcp命令指向导入文件,它指定管道符号作为域分隔符,换行符为行分隔符。

bcp AdventureWorks2008R2.Test.Person in
"C:\Temp\Exports\AdventureWorks2008R2.Person.Person.csv" -T -c -t "|" -r "\n"

一旦命令被创建,我们需要传递给Invoke-Expression。

Invoke-Expression $cmdimport

我们也使用Start-Sleep cmdlet添加延迟,延迟间隔为2秒,在我们计数前可以INSERT。这是避免竞争的一种间单方式,但对于本方案的目的来说,已经足够了。

2.21.4 请参阅…

使用BULK INSERT实施批量导入方案
使用bcp实施批量导出方案
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

上一篇:麻省理工成立金融科技实验室,蚂蚁金服成唯一中国创始企业


下一篇:开户功能遭入侵攻击,银行 App 数据安全如何保护?