3

我正在通过Invoke-Sqlcmd脚本导出大约 1,000,000 行,并将其导出到大约 180MB 的 csv 中。

我想做的是能够将它导出到 10 100,000 行文件中。我该怎么做,因为它似乎不是一个功能Export-CsvInvoke-Sqlcmd我可以找到。

当前代码:

$dataSubset = "mydata"
$localFile = ("{0}.csv" -f $dataSubset)
$localPath = "my\path"
$serverInstance = "myserver.domain.com"
$database = "mydatabase"

$Query = @"
my crazy ass query
"@
$Results = Invoke-Sqlcmd -QueryTimeout 0 -ServerInstance $ServerInstance -Database $database -Query $Query
$Results | Export-csv $localPath/$localFile -NoTypeInformation

mydata.csv我不想拥有一个,而是拥有mydata_1.csv,mydata_2.csv等。

4

3 回答 3

2

不幸的是,从 PowerShell 7.0 开始,PowerShell 中没有批处理(分块)机制。

现在,您必须实现自己的:

# ... 

$batchSize = 10000
$fileNdx = 0

# The list to hold a batch.
$batch = [Collections.Generic.List[object]]::new($batchSize)

# The script block for exporting a single batch to a CSV.
# Exports to .../mydata_1.csv, .../mydata_2.csv, ... 
$sb = { 
        ++$fileNdx; 
        $batch | Export-Csv -NoTypeInformation "$localPath/mydata_$fileNdx.csv" 
      }

Invoke-Sqlcmd -QueryTimeout 0 -ServerInstance $ServerInstance -Database $database -Query $Query |
  ForEach-Object -Process {
    $batch.Add($_) # add object to current batch
    if ($batch.Count -eq $batchSize) { # batch is complete
      . $sb # export
      $batch.Clear() # start new batch
    }
  } -End { 
    if ($batch.Count) { # final, incomplete batch
      . $sb # export
    }
  }

请注意,您通常应该避免使用大型查询,因为它总是将整个结果集作为一个整体$Results = Invoke-Sqlcmd ...收集在内存中- 相反,请使用pipeline及其逐个对象处理,如上所示。 也就是说,如果您有足够的内存,一次捕获所有输入可以根据情况提高性能。

于 2020-05-21T22:14:03.987 回答
2

使用Select-Objectcmdlet(其内置别名为select),它具有-Skip-First参数:

for ($i=0; $i -lt 10; $i++) {
    $localFile = ("{0}_{1}.csv" -f $dataSubset, $i)
    $Results | Select -Skip ($i * 100000) -First 100000 | Export-Csv $localPath/$localFile -NoTypeInformation
}
于 2020-05-21T21:12:11.373 回答
0

我不认为powershell是做到这一点的方法。您不能通过 cmd 集成直接从 SQL Server 导出吗?

无论如何,关于你的问题,另一个选择是:

$length = $Results.length


$items = 10;
$stepwitch = [Math]::Ceiling($length / $items)

for($i=1;$i -le $items; $i++) {
$firstItem = ($i - 1) * $stepwitch 
$lastItem = ($i * $stepwitch) - 1
if ($lastItem -gt $length) {$lastItem = $length}
echo ("FI: " + $firstItem + " LI:"  + $lastItem)
$localFile = ("{($i)}.csv" -f $dataSubset)
$Results[$firstItem..$lastItem] | Export-csv $localPath/$localFile -NoTypeInformation
}

(未经测试,但最后类似于 Mark Arends 解决方案)

另一种选择可能是使用 .net 方法 system.array.copy https://docs.microsoft.com/de-de/dotnet/api/system.array.copy?view=netcore-3.1

于 2020-05-21T21:14:57.490 回答