You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell中通过CSV字段匹配SQL数据生成OUR_SKU列的问题

PowerShell计算属性动态匹配SQL数据返回空值的解决方法

问题场景

我正在导入CSV文件,使用PSCustomObject的计算属性修改数据。目前卡在一个计算环节:需要通过CSV中的“Part No”字段,从SQL查询返回的$SKUs数据行对象中查找匹配的自有零件号(ITEMNO),将其作为OUR_SKU列输出到新CSV中。

CSV内容示例

Vendor Code,Part No,Part Description,Bonded,Quantity,PO No,Vendor Ref
TEZ,ABC1234,Dark Blue,No,50,4378923,ORD089234
TEZ,BBC1256,Orange,No,20,4378923,ORD089234
TEZ,ACD1349,Green,No,10,4378923,ORD089234

SQL查询$SKUs返回的数据行

ITEMNO VALUE
TYP-5063 ABC1234
TYP-5037 BBC1256
TYP-8069 ACD1349

现有代码问题

现有代码中,静态值匹配的OUR_SKU字段可正常工作,但尝试使用$_.'PART_NO'动态匹配的OUR_SKU_X字段返回空值。$SKUs和$_.'PART_NO'均有数据,怀疑是语法问题或脚本块中无法使用该变量。

现有代码片段:

$Files = Get-ChildItem -Path "D:\Imports\Test\INVENTORY_HUB_RECEIPTS"
$ProcessingPath = "D:\Imports\Test\INVENTORY_HUB_RECEIPTS\Processing\"
$UKEntity = "TESTTRG"
$HUB_ID = "TEST"
$SKUs = Invoke-Sqlcmd -ServerInstance "localhost" -Database "XXXX" -Query "SELECT RTRIM(ITEMNO) AS ITEMNO, RTRIM(VALUE) AS VALUE FROM [XXXX].[dbo].[ICITEMO] WHERE OPTFIELD = 'CUSTITMNO' AND VALUE <>''"

foreach ($file in $Files) {

    $Content = (Import-Csv -path ($ProcessingPath + $file.Name)) |
    Select-Object @{n='HUB_ID'; e={ $HUB_ID }},
    @{e={$_.'Part No'}; l='PART_NO'},
    @{e={$_.Quantity}; l='QTY_RECEIVED'},
    DATE,
    @{n='ENTITY'; e={ $UKEntity }},
    @{e={$_.'Vendor Ref'.Substring($_.'Vendor Ref'.Length -8)}; l='ORDER_ID'},

    @{n='OUR_SKU'; e={ $SKUs | Where-Object {$($_.VALUE) -eq '123ABC'} | Select-Object -ExpandProperty ITEMNO}},
    @{n='OUR_SKU_X'; e={ $SKUs | Where-Object {$($_.VALUE) -eq $_.'PART_NO'} | Select-Object -ExpandProperty ITEMNO}}

    if ($Content.Count -eq 0) {Remove-Item ($ProcessingPath + $file.Name)} else {$Content | Export-Csv -Path ($ProcessingPath + $file.Name) -NoTypeInformation -Force}
    }

问题原因

在OUR_SKU_X的计算属性脚本块中,嵌套的Where-Object会改变$_的作用域:内层Where-Object里的$_指向的是$SKUs集合中的每一行对象,而非CSV文件的当前行。因此$_.'PART_NO'实际上是在访问$SKUs行的PART_NO属性(不存在),导致匹配失败返回空值。

解决方法

方法1:保存当前行变量到局部变量

在计算属性的脚本块开头,将CSV当前行的PART_NO赋值给一个局部变量,避免作用域冲突:

@{n='OUR_SKU_X'; e={ 
    $currentPartNo = $_.'PART_NO'
    $SKUs | Where-Object {$_.VALUE -eq $currentPartNo} | Select-Object -ExpandProperty ITEMNO
}}

方法2:转换为哈希表提升查找效率

如果$SKUs数据量较大,每次遍历查找会影响性能,建议将$SKUs转换为哈希表(键为VALUE,值为ITEMNO),直接通过键值对查找:

# 先将$SKUs转换为哈希表
$skuMap = @{}
foreach ($sku in $SKUs) {
    $skuMap[$sku.VALUE] = $sku.ITEMNO
}

# 然后在计算属性中直接查找
@{n='OUR_SKU_X'; e={ $skuMap[$_.'PART_NO'] }}

修正后的完整代码

$Files = Get-ChildItem -Path "D:\Imports\Test\INVENTORY_HUB_RECEIPTS"
$ProcessingPath = "D:\Imports\Test\INVENTORY_HUB_RECEIPTS\Processing\"
$UKEntity = "TESTTRG"
$HUB_ID = "TEST"
$SKUs = Invoke-Sqlcmd -ServerInstance "localhost" -Database "XXXX" -Query "SELECT RTRIM(ITEMNO) AS ITEMNO, RTRIM(VALUE) AS VALUE FROM [XXXX].[dbo].[ICITEMO] WHERE OPTFIELD = 'CUSTITMNO' AND VALUE <>''"

# 转换为哈希表提升查找效率
$skuMap = @{}
foreach ($sku in $SKUs) {
    $skuMap[$sku.VALUE] = $sku.ITEMNO
}

foreach ($file in $Files) {
    $Content = Import-Csv -Path (Join-Path $ProcessingPath $file.Name) |
    Select-Object @{n='HUB_ID'; e={ $HUB_ID }},
                  @{e={$_.'Part No'}; l='PART_NO'},
                  @{e={$_.Quantity}; l='QTY_RECEIVED'},
                  DATE,
                  @{n='ENTITY'; e={ $UKEntity }},
                  @{e={$_.'Vendor Ref'.Substring($_.'Vendor Ref'.Length -8)}; l='ORDER_ID'},
                  @{n='OUR_SKU_X'; e={ $skuMap[$_.'PART_NO'] }}

    if (-not $Content) {
        Remove-Item (Join-Path $ProcessingPath $file.Name)
    } else {
        $Content | Export-Csv -Path (Join-Path $ProcessingPath $file.Name) -NoTypeInformation -Force
    }
}

注:代码中替换了($ProcessingPath + $file.Name)为Join-Path,这是PowerShell中拼接路径的更安全规范的方式;同时修正了Export-Csv的参数错误。

内容的提问来源于stack exchange,提问作者ColinA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:55:08