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

PowerShell脚本导出CSV报错:必须声明标量变量'@',生成空文件

问题解决方案

一、核心错误:过滤函数使用逻辑颠倒(导致SQL语法错误与空CSV)

你当前的代码完全搞错了过滤函数的作用时机:Exclude-ColumnsByType是用来过滤PowerShell对象的属性(即SQL查询返回的结果列),但你却把SQL查询字符串$Query传给了它,这会引发两个问题:

  1. 函数处理的是字符串对象的内置属性,而非SQL返回的业务数据,最终生成的$filteredData是无效SQL语句,这就是报错Must declare the scalar variable "@"的根源。
  2. 无效SQL查询返回空结果,自然生成空CSV文件。

修正后的完整代码

function Exclude-ColumnsByType {
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
        $InputObject,
        [Parameter(Mandatory=$true)]
        [string[]]$ExcludeType
    )
    
    $propertiesToInclude = $InputObject | Get-Member -MemberType Properties | Where-Object {$ExcludeType -notcontains $_.TypeNameOfValue} | Select-Object -ExpandProperty Name
    
    $InputObject | Select-Object $propertiesToInclude
}

# 初始化数据库连接
$MyConnection = Connect-DbaInstance -SqlInstance LOCALHOST\MSSQLSERVER -TrustServerCertificate
# 定义需要导出的表列表
$Tables = @("aaaa1_table4", "aaaa1_table5", "newspic")

foreach ($Table in $Tables) {
    # 构建基础查询语句
    $Query = "SELECT * FROM $Table;"
    # 先执行查询获取原始数据对象
    $rawData = Invoke-DbaQuery -SqlInstance $MyConnection -Database cop -Query $Query
    # 对原始数据执行列过滤
    $filteredData = $rawData | Exclude-ColumnsByType -ExcludeType "System.String", "System.DateTime"
    # 构建CSV输出路径
    $CsvPath = "C:\CSVOut\b\" + $Table + ".csv"
    # 导出过滤后的数据到CSV
    $filteredData | Export-Csv -Path $CsvPath -Delimiter "|" -NoTypeInformation -Encoding unicode
}

二、警告处理:Connect-DbaInstance额外参数被忽略

这个警告是因为部分dbatools版本中,-TrustServerCertificate参数不能直接传给Connect-DbaInstance,需要通过以下两种方式修正:

  • 方式一:将证书验证参数移至Invoke-DbaQuery
    移除Connect-DbaInstance的-TrustServerCertificate,将其添加到Invoke-DbaQuery命令中:
    $MyConnection = Connect-DbaInstance -SqlInstance LOCALHOST\MSSQLSERVER
    $rawData = Invoke-DbaQuery -SqlInstance $MyConnection -Database cop -Query $Query -TrustServerCertificate
    
  • 方式二:通过-ConnectionParameter传递参数
    用哈希表封装连接参数,再传给Connect-DbaInstance:
    $connParams = @{ TrustServerCertificate = $true }
    $MyConnection = Connect-DbaInstance -SqlInstance LOCALHOST\MSSQLSERVER -ConnectionParameter $connParams
    

额外优化建议

如果处理的是大数据量表格,建议直接在SQL层面过滤列(而非PowerShell层面),性能会更优。示例代码如下:

foreach ($Table in $Tables) {
    # 查询非字符串、非日期类型的列名
    $columnQuery = @"
        SELECT COLUMN_NAME 
        FROM INFORMATION_SCHEMA.COLUMNS 
        WHERE TABLE_NAME = '$Table' 
        AND DATA_TYPE NOT IN ('varchar', 'nvarchar', 'char', 'nchar', 'datetime', 'datetime2', 'date')
"@
    $columns = Invoke-DbaQuery -SqlInstance $MyConnection -Database cop -Query $columnQuery | Select-Object -ExpandProperty COLUMN_NAME
    $columnList = $columns -join ", "
    $Query = "SELECT $columnList FROM $Table;"
    # 直接导出查询结果
    Invoke-DbaQuery -SqlInstance $MyConnection -Database cop -Query $Query | Export-Csv -Path "C:\CSVOut\b\$Table.csv" -Delimiter "|" -NoTypeInformation -Encoding unicode
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 13:05:21