PowerShell脚本导出CSV报错:必须声明标量变量'@',生成空文件
问题解决方案
一、核心错误:过滤函数使用逻辑颠倒(导致SQL语法错误与空CSV)
你当前的代码完全搞错了过滤函数的作用时机:Exclude-ColumnsByType是用来过滤PowerShell对象的属性(即SQL查询返回的结果列),但你却把SQL查询字符串$Query传给了它,这会引发两个问题:
- 函数处理的是字符串对象的内置属性,而非SQL返回的业务数据,最终生成的
$filteredData是无效SQL语句,这就是报错Must declare the scalar variable "@"的根源。 - 无效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
相关产品推荐
相关产品推荐

