【发布时间】:2019-11-05 01:24:34
【问题描述】:
我正在尝试从大型 json 文档中批量处理行,并将它们插入 SQL Server。
以下代码有效,但一次将 1 行插入 SQL Server 表中。我认为这实际上是每 1000 行。
add-type -path "C:\Program Files\WindowsPowerShell\Modules\newtonsoft.json\1.0.2.201\libs\newtonsoft.json.dll"
install-module sqlserver -AllowClobber
class EliteCoords {
[double] $x
[double] $y
[double] $z
}
class EliteSystem {
[int] $id
[long] $id64
[string] $name
[EliteCoords] $coords
[string] $date
}
$dt = New-Object system.data.datatable
$dt.Columns.Add("ID",[int])
$dt.Columns.Add("ID64",[long])
$dt.Columns.Add("Name",[string])
$dt.Columns.Add("Coordsx",[decimal])
$dt.Columns.Add("Coordsy",[decimal])
$dt.Columns.Add("Coordsz",[decimal])
$dt.Columns.Add("DiscoveryDate",[string])
$stream = (Get-Item c:\code\systemsWithCoordinates.json).OpenText()
$reader = [Newtonsoft.Json.JsonTextReader]::new($stream)
while ($reader.Read()) {
$cnt = 0
$dt.Clear()
while ($cnt -le 1000) {
$cnt = $cnt + 1
if ($reader.TokenType -eq 'StartObject') {
$row = [Newtonsoft.Json.JsonSerializer]::CreateDefault().Deserialize($reader, [EliteSystem])
$dr = $dt.NewRow()
$dr["ID"] = $row.id
$dr["ID64"] = $row.id64
$dr["Name"] = $row.name
$dr["Coordsx"] = $row.coords.x
$dr["Coordsy"] = $row.coords.y
$dr["Coordsz"] = $row.coords.z
$dr["DiscoveryDate"] = $row.date
$dt.Rows.Add($dr)
}
}
write-sqltabledata -ServerInstance ELITEDANGEROUS -Database EDSM -Schema Staging -Table SystemsWithCoordinates -InputData $dt
}
$stream.Close()
我知道问题是因为 if 块被跳过,除了内部 while 循环的第一次迭代之外,因为令牌类型正在从 StartObject 更改为 StartArray。
我尝试在其中添加一个额外的阅读器循环,但当然,它会读取整个文件。
我也尝试只读取数组而不是对象,但当然,由于嵌套的 json,这会失败。
我应该如何构建循环,以便批量处理 1000 行?
【问题讨论】:
-
无法复制。我尝试了一个基本示例,其中
$dt是[system.data.datatable]类型。然后我添加了列来匹配你的。然后我用while循环循环添加虚拟数据。最后我跑了最后的write-sqltabledata。所有 1000 行都同时快速运行。我使用 sqlserver 模块版本 21.1.18121 进行了测试。 -
如果您使用 SQL Server 2016 或更高版本,您可以简单地将 JSON 本身插入数据库,并使用 TSQL 函数对其进行处理。 docs.microsoft.com/en-us/sql/relational-databases/json/…
-
我无法插入整个文档,原因与粉碎时需要批处理行的原因相同。文件是休。这个文件是 5GB,但我有另一个是 90GB。它需要流式传输和批处理,否则根本不实用
-
@AdminOfThings - 我在问题中添加了更多细节,包括目标表的架构。它似乎“忽略”了嵌套的 while
-
您能否验证
$row = [Newtonsoft.Json.JsonSerializer]::CreateDefault().Deserialize($reader, [EliteSystem])行每次$cnt增加时都会产生不同的输出,或者目标是拥有1000 个相同数据的副本?
标签: json powershell json.net