本节书摘来自异步社区出版社《PowerShell V3—SQL Server 2012数据库自动化运维权威指南》一书中的第2章,第2.21节,作者:【加拿大】Donabel Santos,更多章节内容可以访问云栖社区“异步社区”公众号查看。
本方案描述了如何用PowerShell和bcp将CSV文件导入SQL Server。
为了测试导入,首先创建一个类似于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 ) GO1.通过“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使用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。这是避免竞争的一种间单方式,但对于本方案的目的来说,已经足够了。
使用BULK INSERT实施批量导入方案使用bcp实施批量导出方案本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。
相关资源:敏捷开发V1.0.pptx