在 PowerShell 中使用 @ExpertMode = 1 執行 sp_AskBrent
我正在嘗試
sp_AskBrent
使用 PowerShell 從 PowerShell執行Invoke-SQLCmd
並在變數中擷取其輸出:$query = "EXEC SAIDBA.monitoring.sp_AskBrent @Seconds=10;" $check = Invoke-Sqlcmd -ServerInstance $ServerInstance -Query $query -ErrorAction Stop -ConnectionTimeout 3
使用ExpertMode = 0執行時,沒問題。
但是當以ExpertMode = 1執行時,我們注意到三件事:
- 它將每個數據輸出到外殼
$check
一片空白- 它以以下錯誤結束:
Invoke-Sqlcmd:SQL PowerShell 中不允許出現重複的列名。要重複列,請使用 Column_Name AS New_Name 格式的重複列的列別名。
在行:1 字元:18
* $ check = Invoke-Sqlcmd -ServerInstance $ ServerInstance -Query $query -Er … * 類別資訊:語法錯誤:(:)$$ Invoke-Sqlcmd $$, SqlPowerShellSqlExecutionException * FullyQualifiedErrorId : DuplicateColumnNameErrorMessage, Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
我認為有一種解決方法可以提供參數
sp_AskBrent
以將ExpertMode數據儲存到表中,然後從這些表中進行選擇,但我想確保無法在 PowerShell 中立即恢復所有內容。
不要低估布倫特的回答(儘管他有時在訓練中給出了一些好的答案)……
在 PowerShell 中,您可以執行返回多個數據集的查詢,但您不能使用它來執行此操作
Invoke-Sqlcmd
,因為它目前不是為它建構的。您將有兩種選擇,使用 .NET 本機程式碼(例如
System.Data.SqlClient
)或使用可信賴的SMO
.SMO
如果我想包含伺服器屬性或其他可以訪問的東西,我傾向於簡單地選擇SMO
。在上下文中,
sp_AskBrent
我花了幾分鐘將輸出建構到 HTML 報告中。此腳本的主要興趣點是,要處理多個數據集,您將ExecuteWithResults
使用以下命名空間下可用的方法執行查詢:
Microsoft.SqlServer.Management.Smo.Server
Microsoft.SqlServer.Management.Smo.Database
database
您可以在此處查看使用 MSDN 上的命名空間的範例。在我的腳本中,我使用了Server
命名空間。無論哪種方式都可以,但是如果您查看 MSDN 文章,ExecuteWithResults
它將返回一個DataSet
對象,並且該對象將包含一個DataTable
. 數量DataTables
基於您的程式碼返回的數據集數量。在布倫特程序的情況下,您將得到 5DataTables
。您可以在下面的程式碼中通過在循環$results.Count
之前添加 in 來驗證這一點。foreach
現在這個腳本中的另一個注意事項是我選擇輸出到 HTML。如果需要,您可以選擇另一種格式,但將所有內容輸出到控制台是不可讀的。我還會注意到我添加了幫助資訊,因此
Get-Help
如果您需要查看參數的詳細資訊或提醒自己如何呼叫它,您可以針對腳本使用。對於這個範例,我使用了來自 Pinal Dave 的一小段程式碼來在我的本地實例上生成一些 CPU 使用率。(否則程序沒有返回太多資訊)。
腳本
<# .SYNOPSIS Executes sp_AskBrent and outputs to HTML .DESCRIPTION Execute sp_AskBrent in normal or expert mode and outputs to an HTML. .PARAMETER server String. [REQUIRED] The SQL Server instance you wish to get results on. .PARAMETER timelimit Integer. Time used for @seconds parameter of sp_AskBrent .PARAMETER expertMode Switch. Just opts to have @ExpertMode = 1 for the query .PARAMETER sqlversion Integer. If on machine with multiple SQL Server tool versions installed, specify version. .PARAMETER outfile String. Set output file to generate HTML .EXAMPLE Run command in normal mode, which returns one dataset .\Script.ps1 -server MANATARMS\SQL12 -timelimit 5 -sqlversion 11 -outfile 'C:\temp\MyServer.html' .EXAMPLE Run command in expert mode, which returns multiple datasets .\Script.ps1 -server MANATARMS\SQL12 -timelimit 5 -expertMode -sqlversion 11 -outfile 'C:\temp\MyServer.html' .NOTES Does not check if sp_AskBrent is on the server before executing the query. #> [cmdletbinding()] param( [Parameter(Mandatory=$true,Position=0)] [Alias("instance")] [string] $server, [Parameter(Mandatory=$false,Position=1)] [int] $timelimit = 10, [Parameter(Mandatory=$false,Position=2)] [switch] $expertMode, [Parameter(Mandatory=$false,Position=3)] [int] $sqlversion = 11, [Parameter(Mandatory=$false,Position=4)] [string] $outfile= 'C:\temp\Testing.html' ) $HtmlTop = @" <!DOCTYPE html> <html> <head> <style> body { background-color:white; font-family:Tahoma,Arial; font-size:10pt; } table { border-collapse: collapse; } th { border:2px solid black; color:white; background-color: #0066FF; padding: 4px; } th.subhead { color:black; background-color: #8dbafc } td { border: 1px solid black; padding: 2px; } </style> </head> <body> <h2>Server Name: $($server)</h2> <h3>Run Date: $(Get-Date)</h3> "@ $HtmlTop | Out-File -FilePath $outfile -Force if ($expertMode) { $askBrent = "EXEC sp_AskBrent @Seconds=$($timelimit), @ExpertMode=1" } else { $askBrent = "EXEC sp_AskBrent @Seconds=$($timelimit), @ExpertMode=0" } try { Add-Type -AssemblyName "Microsoft.SqlServer.Smo,Version=$($sqlversion).0.0.0,Culture=neutral,PublicKeyToken=89845dcd8080cc91" } catch { Add-Type -AssemblyName "Microsoft.SqlServer.Smo" } $srv = New-Object 'Microsoft.SqlServer.Management.Smo.Server' $server $results = $srv.ConnectionContext.ExecuteWithResults($askBrent); foreach ($t in $results.Tables) { $t | Select-Object * -ExcludeProperty RowError, RowState, HasErrors, Table, ItemArray | ConvertTo-Html -As Table -Fragment | Out-String | Out-File -FilePath $outfile -Append ## This is just to get a break between tables ## "<hr>" | Out-File -FilePath $outfile -Append }