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

遍历计算机名列表匹配脚本异常:全设0且运行缓慢求助

嘿,我帮你捋捋这个脚本的问题,顺便给你几个靠谱的修复方案~

问题根源分析

1. 全表更新导致最终全为0

你的内层foreach循环里,执行UPDATE语句时没有加WHERE条件!这意味着每一次循环都会把inv表的所有行的amp字段全部覆盖一遍。哪怕某次匹配成功把某行设成了1,下一次遇到不匹配的主机名时,又会把所有行(包括刚设为1的那行)改回0,最后自然全是0。

2. 嵌套循环+高频数据库请求导致速度极慢

你现在的逻辑是:

  • 遍历ad表的每台电脑,先插入一行到inv表
  • 再遍历amp表的每台电脑,每遍历一次就发一次UPDATE请求
    如果ad有100台、amp有100台,那就是100次INSERT + 10000次UPDATE,数据库请求次数直接爆炸,速度快才怪。

3. 隐藏的SQL注入风险

直接把$adcompName拼进SQL语句里,如果电脑名带单引号或者特殊字符,脚本会直接报错,甚至存在SQL注入风险。

修复方案

方案一:用纯SQL完成推荐!效率拉满

其实这个需求完全可以交给数据库一次性搞定,根本不需要PowerShell做嵌套循环,速度快到飞起:

-- 清空inv表(如果需要全量更新的话)
TRUNCATE TABLE inv;

-- 一次性插入所有ad电脑名,并自动匹配amp状态
INSERT INTO inv (ComputerName, amp)
SELECT 
    ad.ComputerName,
    CASE WHEN amp.HostName IS NOT NULL THEN '1' ELSE '0' END AS amp
FROM ad
LEFT JOIN amp ON ad.ComputerName = amp.HostName;

如果inv表已经有数据,只需要更新amp字段的话,用这个:

UPDATE inv
JOIN ad ON inv.ComputerName = ad.ComputerName
LEFT JOIN amp ON ad.ComputerName = amp.HostName
SET inv.amp = CASE WHEN amp.HostName IS NOT NULL THEN '1' ELSE '0' END;

方案二:优化PowerShell脚本如果一定要用PowerShell

如果必须用PowerShell实现,我们可以先把amp的主机名存进哈希集合(快速查找),再减少数据库请求次数:

# 先把amp的所有主机名存入哈希集合,实现O(1)快速查找
$ampHosts = [System.Collections.Generic.HashSet[string]]::new()
$ampcompdata = Invoke-MySqlQuery -query "SELECT HostName FROM amp"
foreach ($item in $ampcompdata) {
    [void]$ampHosts.Add($item.HostName)
}

# 遍历ad表数据,逐个处理并插入(或更新)
$adcompdata = Invoke-MySqlQuery -query "SELECT ComputerName FROM ad"
foreach ($adcompitem in $adcompdata) {
    $adcompName = $adcompitem.ComputerName
    $matchStatus = if ($ampHosts.Contains($adcompName)) { '1' } else { '0' }

    # 用参数化查询插入数据,避免SQL注入
    Invoke-MySqlQuery -Query "INSERT INTO inv(ComputerName, amp) VALUES(@name, @amp)" -Parameters @{
        name = $adcompName
        amp = $matchStatus
    }

    # 如果是更新已有数据,记得加WHERE条件指定行
    # Invoke-MySqlQuery -Query "UPDATE inv SET amp = @amp WHERE ComputerName = @name" -Parameters @{
    #     name = $adcompName
    #     amp = $matchStatus
    # }

    Write-Host "处理完成:$adcompName,匹配状态:$(if ($matchStatus -eq '1') {'匹配'} else {'不匹配'})"
}

这个优化的核心点:

  • 哈希集合让主机名匹配速度从O(n)变成O(1)
  • 每个ad电脑只触发1次数据库请求,总请求数从O(n*m)降到O(n+m)
  • 参数化查询避免了SQL注入,还能处理带特殊字符的电脑名
  • 每次操作都指定了目标行,不会误改其他数据
关于调试时匹配项仍为0的原因

当你匹配到"015598793153"时,执行的UPDATE inv SET amp = '1'会把全表的amp都改成1,但内层循环还会继续遍历amp表的其他主机名,下一次不匹配时,又会执行UPDATE inv SET amp = '0'再次全表覆盖,所以那行最后又被改回0了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:13:32