Powershell foreach SQL 服务器查询随机整理DataSet
Powershell foreach SQL Server query randomly collates DataSet
我需要制作一个简单的管理脚本来检查 14 SQL 服务器的 table。
我最终使用了 Adam's script from this 个问题。
然而,当 运行 时,它会跳过随机数量的服务器的发布结果,然后将它们的查询转储到一个 table 中,然后单独处理任何剩余的服务器。我做错了什么? (因为我无法评论 Adam 的回答)
我不介意整理 table 中的所有数据并在最后转储,但如果更容易完成的话,然后使用服务器名称和结果列。
这是我的脚本,示例输出如下;
$year = Get-Date -Format yyyy
$servers = gc 'ServerList.txt'
foreach ($server in $servers)
{
try
{
$ServerName = "$server"
$DatabaseName = "DatabaseName"
$Query = "select count(*) from Alarm_Activations where Activation_Date not like '%$year%'"
#$ds = $null -Tried adding this to fix the issue
#Timeout parameters
$QueryTimeout = 120
$ConnectionTimeout = 30
Write-Host ""
Write-Host ""
Write-Host " Checking $server "
#Action of connecting to the Database and executing the query and returning results if there were any.
$conn = New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Data Source=$server\sqlexpress;Initial Catalog=DatabaseName;Connect Timeout=30; Integrated security=true;"
$conn.ConnectionString = $ConnectionString
$conn.Open()
$cmd = New-Object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout = $QueryTimeout
$ds = New-Object system.Data.DataSet
$da = New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
$conn.Close()
Write-Host "Number of activations older than $year :"
$ds.Tables
}
catch
{
Write-Error "Something went wrong. Seems you have to do it manually!"
return
}
}
示例输出
转储 table 的点似乎是随机的,但通常超过一半的服务器。
最早看到的是Server-5,最新的;服务器 14;
& CheckAlarmActivation.ps1
Checking Server-1
Number of activations older than 2019 :
Checking Server-2
Number of activations older than 2019 :
Checking Server-3
Number of activations older than 2019 :
Checking Server-4
Number of activations older than 2019 :
Checking Server-5
Number of activations older than 2019 :
Checking Server-6
Number of activations older than 2019 :
Checking Server-7
Number of activations older than 2019 :
Checking Server-8
Number of activations older than 2019 :
Checking Server-9
Number of activations older than 2019 :
Checking Server-10
Number of activations older than 2019 :
Column1
-------
0
0
0
3318
1069
4375
8
9357
74
1735
Checking Server-11
Number of activations older than 2019 :
7917
Checking Server-12
Number of activations older than 2019 :
3583
Checking Server-13
Number of activations older than 2019 :
5622
Checking Server-14
Number of activations older than 2019 :
4166
就像 AdminOfThings 评论的那样,使用 Write-Output
而不是 Write-Host
。因为您正在使用 Write-Host
流并且只是输出一个变量(进入输出流)($ds.Tables
),所以您不会同时在控制台上看到两个流。
除了使用 Write-Output
之外,我会通过将您的数据库调用的结果(以及您希望从中 return 获得的任何结果)存储为您放入集合,然后在遍历所有服务器后,您可以一次性格式化输出(用于控制台、生成 csv/html 报告等)。这种方法的好处是,如果其中一台服务器出现故障,您的脚本不会失败。
编辑 我更新了 catch 块以正确获取异常。我还更新了从数据集中获取值的位置以展开,因此您没有数据行对象。如果您有多个列,或者您希望根据某些列创建计算属性,则可以使用更高级的 Select-Object
逻辑。 SO post with more info。在您的情况下,您只想取回记录数。
$serverResults = @()
$servers = "srv1","srv2"
foreach ($server in $servers)
{
# Create an instance of a custom object that will hold the results of your query. Add properties as needed, they can be other complex objects, or simple types.
$serverResultInstance = New-Object PSObject -Property @{
ServerName = $server
DatabaseName = $DatabaseName
Tables = $null
Exception = $null
}
try{
#Connect to DB like you do (Don't use Write-Host)
#Add your dataset for this instance
$ServerName = "$server"
$DatabaseName = "dbName"
$Query = "select count(*) from sys.columns"
#$ds = $null -Tried adding this to fix the issue
#Timeout parameters
$QueryTimeout = 120
$ConnectionTimeout = 30
Write-Host ""
Write-Host ""
Write-Host "Checking $server"
#Action of connecting to the Database and executing the query and returning results if there were any.
$conn = New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Data Source=$server;Initial Catalog=$DatabaseName;Connect Timeout=$ConnectionTimeout; Integrated security=true;"
$conn.ConnectionString = $ConnectionString
$conn.Open()
$cmd = New-Object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout = $QueryTimeout
$ds = New-Object system.Data.DataSet
$da = New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
# Instead of keeping the whole table/row object, expand out the column you want. If you have multiple columns or tables in your dataset you would need to change these values.
$serverResultInstance.Tables = $ds.Tables[0] | select -ExpandProperty Column1
}
catch{
#This should have been $_.Exception
$serverResultInstance.Exception = $_.Exception
}
finally{
$conn.Close()
$serverResults += $serverResultInstance
}
}
foreach($result in $serverResultInstance){
# Format your output here. Make a csv, send an email, etc. Or just:
Write-Output "Number of activations older than $year :"
Write-Output $result.Tables
}
我需要制作一个简单的管理脚本来检查 14 SQL 服务器的 table。 我最终使用了 Adam's script from this 个问题。
然而,当 运行 时,它会跳过随机数量的服务器的发布结果,然后将它们的查询转储到一个 table 中,然后单独处理任何剩余的服务器。我做错了什么? (因为我无法评论 Adam 的回答)
我不介意整理 table 中的所有数据并在最后转储,但如果更容易完成的话,然后使用服务器名称和结果列。
这是我的脚本,示例输出如下;
$year = Get-Date -Format yyyy
$servers = gc 'ServerList.txt'
foreach ($server in $servers)
{
try
{
$ServerName = "$server"
$DatabaseName = "DatabaseName"
$Query = "select count(*) from Alarm_Activations where Activation_Date not like '%$year%'"
#$ds = $null -Tried adding this to fix the issue
#Timeout parameters
$QueryTimeout = 120
$ConnectionTimeout = 30
Write-Host ""
Write-Host ""
Write-Host " Checking $server "
#Action of connecting to the Database and executing the query and returning results if there were any.
$conn = New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Data Source=$server\sqlexpress;Initial Catalog=DatabaseName;Connect Timeout=30; Integrated security=true;"
$conn.ConnectionString = $ConnectionString
$conn.Open()
$cmd = New-Object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout = $QueryTimeout
$ds = New-Object system.Data.DataSet
$da = New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
$conn.Close()
Write-Host "Number of activations older than $year :"
$ds.Tables
}
catch
{
Write-Error "Something went wrong. Seems you have to do it manually!"
return
}
}
示例输出
转储 table 的点似乎是随机的,但通常超过一半的服务器。
最早看到的是Server-5,最新的;服务器 14;
& CheckAlarmActivation.ps1
Checking Server-1
Number of activations older than 2019 :
Checking Server-2
Number of activations older than 2019 :
Checking Server-3
Number of activations older than 2019 :
Checking Server-4
Number of activations older than 2019 :
Checking Server-5
Number of activations older than 2019 :
Checking Server-6
Number of activations older than 2019 :
Checking Server-7
Number of activations older than 2019 :
Checking Server-8
Number of activations older than 2019 :
Checking Server-9
Number of activations older than 2019 :
Checking Server-10
Number of activations older than 2019 :
Column1
-------
0
0
0
3318
1069
4375
8
9357
74
1735
Checking Server-11
Number of activations older than 2019 :
7917
Checking Server-12
Number of activations older than 2019 :
3583
Checking Server-13
Number of activations older than 2019 :
5622
Checking Server-14
Number of activations older than 2019 :
4166
就像 AdminOfThings 评论的那样,使用 Write-Output
而不是 Write-Host
。因为您正在使用 Write-Host
流并且只是输出一个变量(进入输出流)($ds.Tables
),所以您不会同时在控制台上看到两个流。
除了使用 Write-Output
之外,我会通过将您的数据库调用的结果(以及您希望从中 return 获得的任何结果)存储为您放入集合,然后在遍历所有服务器后,您可以一次性格式化输出(用于控制台、生成 csv/html 报告等)。这种方法的好处是,如果其中一台服务器出现故障,您的脚本不会失败。
编辑 我更新了 catch 块以正确获取异常。我还更新了从数据集中获取值的位置以展开,因此您没有数据行对象。如果您有多个列,或者您希望根据某些列创建计算属性,则可以使用更高级的 Select-Object
逻辑。 SO post with more info。在您的情况下,您只想取回记录数。
$serverResults = @()
$servers = "srv1","srv2"
foreach ($server in $servers)
{
# Create an instance of a custom object that will hold the results of your query. Add properties as needed, they can be other complex objects, or simple types.
$serverResultInstance = New-Object PSObject -Property @{
ServerName = $server
DatabaseName = $DatabaseName
Tables = $null
Exception = $null
}
try{
#Connect to DB like you do (Don't use Write-Host)
#Add your dataset for this instance
$ServerName = "$server"
$DatabaseName = "dbName"
$Query = "select count(*) from sys.columns"
#$ds = $null -Tried adding this to fix the issue
#Timeout parameters
$QueryTimeout = 120
$ConnectionTimeout = 30
Write-Host ""
Write-Host ""
Write-Host "Checking $server"
#Action of connecting to the Database and executing the query and returning results if there were any.
$conn = New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Data Source=$server;Initial Catalog=$DatabaseName;Connect Timeout=$ConnectionTimeout; Integrated security=true;"
$conn.ConnectionString = $ConnectionString
$conn.Open()
$cmd = New-Object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout = $QueryTimeout
$ds = New-Object system.Data.DataSet
$da = New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
# Instead of keeping the whole table/row object, expand out the column you want. If you have multiple columns or tables in your dataset you would need to change these values.
$serverResultInstance.Tables = $ds.Tables[0] | select -ExpandProperty Column1
}
catch{
#This should have been $_.Exception
$serverResultInstance.Exception = $_.Exception
}
finally{
$conn.Close()
$serverResults += $serverResultInstance
}
}
foreach($result in $serverResultInstance){
# Format your output here. Make a csv, send an email, etc. Or just:
Write-Output "Number of activations older than $year :"
Write-Output $result.Tables
}