【问题标题】:Powershell function to import csv file to SQL Server database tablePowershell 函数将 csv 文件导入 SQL Server 数据库表
【发布时间】:2019-09-20 06:30:55
【问题描述】:

我创建了一个 PowerShell 函数,它从 .csv 文件(第一行是标题)批量复制数据,并将数据插入到 SQL Server 数据库表中。

查看我的代码:

function BulkCsvImport($sqlserver, $database, $table, $csvfile, $csvdelimiter, $firstrowcolumnnames) {
    Write-Host "Bulk Import Started." 
    $elapsed = [System.Diagnostics.Stopwatch]::StartNew()  
    [void][Reflection.Assembly]::LoadWithPartialName("System.Data") 
    [void][Reflection.Assembly]::LoadWithPartialName("System.Data.SqlClient") 

    # 50k worked fastest and kept memory usage to a minimum 
    $batchsize = 50000 

    # Build the sqlbulkcopy connection, and set the timeout to infinite 
    $connectionstring = "Data Source=$sqlserver;Integrated Security=true;Initial Catalog=$database;" 

    # Wipe the bulk insert table first
    Invoke-Sqlcmd -Query "TRUNCATE TABLE $table" -ServerInstance $sqlserver -Database $database

    $bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($connectionstring, [System.Data.SqlClient.SqlBulkCopyOptions]::TableLock) 
    $bulkcopy.DestinationTableName = $table 
    $bulkcopy.bulkcopyTimeout = 0 
    $bulkcopy.batchsize = $batchsize 

    # Create the datatable, and autogenerate the columns. 
    $datatable = New-Object System.Data.DataTable 

    # Open the text file from disk 
    $reader = New-Object System.IO.StreamReader($csvfile) 
    $columns = (Get-Content $csvfile -First 1).Split($csvdelimiter) 

    if ($firstrowcolumnnames -eq $true) { $null = $reader.readLine() } 

    foreach ($column in $columns) {  
        $null = $datatable.Columns.Add() 
    } 

    # Read in the data, line by line 
    while (($line = $reader.ReadLine()) -ne $null)  { 
        $null = $datatable.Rows.Add($line.Split($csvdelimiter)) 

        $i++; 
        if (($i % $batchsize) -eq 0) {  
            $bulkcopy.WriteToServer($datatable)  
            Write-Host "$i rows have been inserted in $($elapsed.Elapsed.ToString())." 
            $datatable.Clear()  
        }  
    }  

    # Add in all the remaining rows since the last clear 
    if($datatable.Rows.Count -gt 0) { 
        $bulkcopy.WriteToServer($datatable) 
        $datatable.Clear() 
    } 

    # Clean Up 
    $reader.Close(); 
    $reader.Dispose() 

    $bulkcopy.Close(); 
    $bulkcopy.Dispose() 

    $datatable.Dispose() 

    Write-Host "Bulk Import Completed. $i rows have been inserted into the database." 
    # Write-Host "Total Elapsed Time: $($elapsed.Elapsed.ToString())" 
    # Sometimes the Garbage Collector takes too long to clear the huge datatable. 
    $i = 0
    [System.GC]::Collect()
}

我希望修改上述内容,以便.csv 文件中的列名与 SQL Server 数据库表中的列名匹配。它们应该是相同的。目前正在将数据导入到不正确的数据库列中。

我可以得到一些帮助来修改上述功能以实现此目的吗?

【问题讨论】:

  • 使用批量插入可以轻松完成的代码如此之多。 sqlservercentral.com/articles/…
  • 或者只是在 ssms 中导入平面文件。但是,问题可能是表列的序号与 csv 文件中的序号不匹配。此外,您没有指定要批量插入的格式文件,因此您是在自找麻烦。
  • @user1443098 SSMS/SSIS 可能并不总是选项。作者想用 PS 自动化什么?

标签: sql-server powershell csv import


【解决方案1】:

我会使用现有的开源解决方案:

Import-DbaCsv - dbatools.io

Import-DbaCsv.ps1

高效地将非常大(和小)的 CSV 文件导入 SQL Server。

Import-DbaCsv 利用 .NET 的超快速 SqlBulkCopy 类将 CSV 文件导入 SQL Server。


参数:

-ColumnMap

默认情况下,大容量复制会尝试自动映射列。当它不 根据需要工作,此参数将有所帮助。

PS C:\> $columns = @{
>> Text = 'FirstName'
>> Number = 'PhoneNumber'
>> }
PS C:\> Import-DbaCsv -Path c:\temp\supersmall.csv 
        -SqlInstance sql2016 -Database tempdb -ColumnMap $columns 
        -BatchSize 50000 -Table table_name -Truncate

CSV 列“Text”被插入到 SQL 列“FirstName”中,CSV 列 Number 被插入到 SQL 列“PhoneNumber”中。所有其他列都被忽略,因此为 null 或默认值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    • 2023-02-01
    • 2012-05-06
    • 1970-01-01
    相关资源
    最近更新 更多