我不时地下载一些脚本(总是在相同的程序包中包含或多或少的相同文件)。我编写了一个powershell脚本,用于下载master.zip,解压缩,将文件复制到其他位置,然后进行清理。
现在,我想在所有服务器上运行.sql文件,因此服务器上始终具有最新版本。
我写了这个powershell脚本
Function Install-BrentFirstResponderKit
{
param(
$server= @("server1","server2")
)
$path = "$env:USERPROFILE\AppData\Roaming\Microsoft\SQL Server Management Studio\14.0\Templates\Sql\_Monitoring\Brent"
$onlyFiles = ("sp_Blitz.sql","sp_BlitzCache.sql","sp_BlitzFirst.sql","sp_BlitzIndex.sql","sp_BlitzLock.sql","sp_BlitzWho.sql", "sp_TEST")
$files = Get-ChildItem $path\* -Include $onlyFiles
# Credentials to access SQL-Server
$credential = Get-Credential -username myadmin -Message "Credentials"
$username = $credential.UserName
$password = $credential.Password
$password.MakeReadOnly()
$creds = New-Object System.Data.SqlClient.SqlCredential($username, $password)
# Create SQL Connection Object
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
foreach($srv in $server)
{
# Open SQL connection
$SqlConnection.ConnectionString = "Server=$srv; Database=master; Integrated Security=false"
$SqlConnection.Credential = $creds
$SqlConnection.Open()
# Execute SQL Statement
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandTimeout = 0
foreach($file in $files)
{
$SqlCmd.CommandText = Get-Content $file -Raw
$SqlCmd.Connection = $SqlConnection
$sqlcmd.ExecuteScalar()
}
$sqlConnection.Close()
}
}
运行powershell脚本时,出现以下错误:
Ausnahme beim Aufrufen von“ ExecuteScalar” mit 0参数: “'CREATE / ALTER PROCEDURE'必须是查询中的第一条语句 批”。在Zeile:1 Zeichen:1 + $ sqlcmd.ExecuteScalar() + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:未指定:(:) [],MethodInvocationException + FullyQualifiedErrorId:SqlException
还是这个错误,取决于我运行的文件:
Ausnahme beim Aufrufen von“ ExecuteScalar” mit 0参数: “关键字'ALTER'附近的语法不正确。'CREATE/ ALTER PROCEDURE' 必须是查询批处理中的第一条语句。语法不正确 'GO'。“在Zeile:1 Zeichen:1 + $ sqlcmd.ExecuteScalar() + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:未指定:(:) [],MethodInvocationException + FullyQualifiedErrorId:SqlException
.sql文件的构建方式都相同:
IF OBJECT_ID('dbo.sp_TEST') IS NULL
EXEC ('CREATE PROCEDURE dbo.sp_TEST AS RETURN 0;')
GO
ALTER PROCEDURE dbo.sp_TEST
AS
BEGIN
Select @@Version
END
GO
虽然我了解错误消息并找到了解决方法(手动删除IF块并删除所有GO消息),但这不是我想要的。
如果我必须手动编辑文件(或者可以用$sqlcmd.SelectCommand = $sqlcmd.SelectCommand.Replace(<if-block>,'')
编写脚本),也可以直接手动安装它们。
所以,我的问题是,为什么我不能运行以Create / Alter以外的其他开头的脚本?我想念什么?
感谢您的帮助。
PS:我不知道它是否可以与Invoke-SqlCmd一起使用,但是我的服务器位于不同的域中,过去,我在使用Invoke-SqlCmd时遇到了一些问题
@Aaron:如果运行Get-Content $file -Raw
,我将得到以下输出结果
如果OBJECT_ID('dbo.sp_TEST')为NULL
EXEC(“创建过程” dbo.sp_TEST AS RETURN 0;')
GO更改过程dbo.sp_TEST
AS
开始
选择@@ Version
END
开始
这正是$sqlcmd.CommandText
编辑:关于Dan Guzmans的评论,我将代码更改为以下代码,并且现在可以正常工作:
Function Install-BrentFirstResponderKitV2
{
param(
[string[]]$server= @("server1","server2")
)
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
#alle dateien finden, welche installiert werden sollen
$path = "$env:USERPROFILE\AppData\Roaming\Microsoft\SQL Server Management Studio\14.0\Templates\Sql\_Monitoring\Brent"
$onlyFiles = ("sp_Blitz.sql","sp_BlitzCache.sql","sp_BlitzFirst.sql","sp_BlitzIndex.sql","sp_BlitzLock.sql","sp_BlitzWho.sql","sp_TEST.sql")
$files = Get-ChildItem $path\* -Include $onlyFiles
# Credentials für den Zugriff auf die SQL Server einlesen
$credential = Get-Credential -username myadmin -Message "Credentials"
foreach($srv in $server)
{
$x = $sqlConnection = New-Object Microsoft.SqlServer.Management.Smo.Server $srv
$x.ConnectionContext.LoginSecure = $false
$x.ConnectionContext.set_Login($credential.username)
$x.ConnectionContext.set_SecurePassword($credential.password)
$x.ConnectionContext.Connect()
foreach($file in $files)
{
Invoke-Sqlcmd -Database master -Query $(Get-Content $file -Raw) -ServerInstance $x -Username $credential.UserName -Password $credential.GetNetworkCredential().Password
}
$x.ConnectionContext.Disconnect()
}
}