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

使用SQL NOT IN子句时变量传递异常,更新结果与预期相反

SQL NOT IN 更新结果与预期相反的问题解决

你的代码逻辑存在核心问题:循环遍历每个VM时,每次执行NOT IN ('单个VMID'),这会导致每次循环都把除当前VMID外的所有行更新一遍。比如你有VM1、VM2、VM3三个VM,第一次循环更新除VM1外的所有行,第二次更新除VM2外的所有行,第三次更新除VM3外的所有行,最终只有最后一个VMID对应的行没被更新,其他行被反复修改,结果自然和你“排除所有VMs集合里的VMID”的预期完全相反。

以下是两种正确的解决方式:

方法1:批量生成IN列表(适合VM数量不多的场景)

先把所有VMID拼接成逗号分隔的字符串,一次性执行更新语句即可,无需循环:

# 提取所有VMID到数组
$vmIds = $VMs | Select-Object -ExpandProperty VMid
# 转成带单引号的逗号分隔格式,例如 'vm-001','vm-002'
# 若VMID包含单引号,需转义为两个单引号避免SQL语法错误
$idList = $vmIds | ForEach-Object { "'$($_ -replace "'", "''")'" } -join ','

# 单次执行更新
invoke-sqlcmd -Database $Database -server $SQLServer -Query "
UPDATE [table] 
SET Column1=1, Column2=0, column3=GETDATE() 
WHERE table.vmid NOT IN ($idList)
"

方法2:参数化查询(更安全,避免SQL注入)

如果VM数量较多,或者需要规避SQL注入风险,推荐使用表值参数的参数化查询方式:

# 创建存储VMID的DataTable
$dt = New-Object System.Data.DataTable
$dt.Columns.Add("VMid", [string])
foreach ($vm in $VMs) {
    $dt.Rows.Add($vm.VMid)
}

# 建立SQL连接并执行参数化更新
$conn = New-Object System.Data.SqlClient.SqlConnection "Server=$SQLServer;Database=$Database;Integrated Security=True"
$conn.Open()
$cmd = $conn.CreateCommand()
$cmd.CommandText = @"
UPDATE [table] 
SET Column1=1, Column2=0, column3=GETDATE() 
WHERE table.vmid NOT IN (SELECT VMid FROM @VMIds)
"@
# 添加表值参数(需提前在SQL Server创建对应类型)
$param = $cmd.Parameters.Add("@VMIds", [System.Data.SqlDbType]::Structured)
$param.Value = $dt
$param.TypeName = "dbo.VMIdList" # 需先在SQL执行:CREATE TYPE dbo.VMIdList AS TABLE (VMid varchar(100))
$cmd.ExecuteNonQuery()
$conn.Close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:30:43