我正试图使用Powershell将超大的CSV文件加载到SQL Server中。代码还必须应用动态正则表达式替换,允许使用各种分隔符、EOR和EOF标记。为了维护,我真的希望所有这些逻辑都存在于Powershell中,而不导入程序集。
为了提高效率,我知道我需要使用SQLBulkCopy方法。但是,我看到的所有Powershell示例都填充了一个DataTable并传递它,由于文件大小的原因,这对我来说是不可能的。
我确信我需要将StreamReader封装在Idatareader中,然后将其传递给SQLBulkcopy。我发现了几个在C#中实现的很好的例子:
http://archive.msdn.microsoft.com/FlatFileDataReader
http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
是否可以在不导入C#程序集的情况下使用本机PowerShell实现此功能?具体来说,我很难转换抽象类包装器。
到目前为止,这是我所拥有的代码,它没有通过IdataReader,并且突破了内存限制。
function Get-CSVDataReader()
{
param (
[string]$path
)
$parsedData = New-Object 'System.Collections.Generic.List[string]'
#List<string[]> parsedData = new List<string[]>()
$sr = new-object IO.StreamReader($path)
while ($line = $sr.ReadLine())
{
#regex replace and other logic here
$parsedData.Add($line.Split(','))
}
,$parsedData #if this was an idatareader, the comma keeps it from exploding
}
$MyReader = Get-CSVDataReader('This should not fill immediately. It needs a Read Method.')
非常感谢大家的帮助。
如果你只想使用带有SqlBulkCopy的DataReader,你可以使用Office 2007/2010附带的ACE驱动程序,也可以单独下载,打开与CSV文件的OLEDB连接,打开读取器并调用WriteToServer
$ServerInstance = "$env:computernamesql1"
$Database = "tempdb"
$tableName = "psdrive"
$ConnectionString = "Server={0};Database={1};Integrated Security=True;" -f $ServerInstance,$Database
$filepath = "C:UsersPublicbin"
get-psdrive | export-csv ./psdrive.csv -NoTypeInformation -Force
$connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=`"$filepath`";Extended Properties=`"text;HDR=yes;FMT=Delimited`";"
$qry = 'select * from [psdrive.csv]'
$conn = new-object System.Data.OleDb.OleDbConnection($connString)
$conn.open()
$cmd = new-object System.Data.OleDb.OleDbCommand($qry,$conn)
$dr = $cmd.ExecuteReader()
$bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $connectionString
$bulkCopy.DestinationTableName = $tableName
$bulkCopy.WriteToServer($dr)
$dr.Close()
$conn.Close()
#CREATE TABLE [dbo].[psdrive](
# [Used] [varchar](1000) NULL,
# [Free] [varchar](1000) NULL,
# [CurrentLocation] [varchar](1000) NULL,
# [Name] [varchar](1000) NULL,
# [Provider] [varchar](1000) NULL,
# [Root] [varchar](1000) NULL,
# [Description] [varchar](1000) NULL,
# [Credential] [varchar](1000) NULL,
# [DisplayRoot] [varchar](1000) NULL
#)
我正在通过数据表导入大型CSV,并在100万行后执行批量更新。
if ($dt.rows.count -eq 1000000) {
$bulkCopy.WriteToServer($dt)
$dt.Clear()
}
这是我在博客上详细介绍自己脚本的链接,但上面的代码概述了基本概念。我的PowerShell脚本花了4.x分钟从1.1 GB的CSV中导入了900万行。该脚本依赖于SqlBulkCopy、[System.IO.File]::OpenText和一个数据表。