3

我正在尝试通过 Azure 自动化为多个 AzureSQL 数据库循环调用 SQLcmd。循环中的第一项执行,但所有其余的都失败了:

Invoke-Sqlcmd:建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称是否正确以及 SQL Server 是否配置为允许远程连接。(提供者:命名管道提供者,错误:40 - 无法打开与 SQL Server 的连接)

我猜我需要在执行下一个之前关闭第一个 invoke-sqlcmd 的连接,但还没有找到直接的方法来使用 invoke-sqlcmd 完成此操作。这是我的循环:

param(      
# Parameters to Pass to PowerShell Scripts
[parameter(Mandatory=$true)][String] $azureSQLServerName = "myazuresql",        
[parameter(Mandatory=$true)][String] $azureSQLCred = "myazureautosqlcred"        
        )

# DB Name Array
$dbnamearray = @("database1","database2","database3")
$dbnamearray

# Datatable Name
$tabName = "RunbookTable"

#Create Table object
$table = New-Object system.Data.DataTable "$tabName"

#Define Columns
$col1 = New-Object system.Data.DataColumn dbname,([string])

#Add the Columns
$table.columns.add($col1)

# Add Row and Values for dname Column
ForEach ($db in $dbnamearray) 
{
$row = $table.NewRow()
$row.dbname = $db
#Add the row to the table
$table.Rows.Add($row)
}

#Display the table
$table | format-table -AutoSize

# Loop through the datatable using the values per column 
$table | ForEach-Object {

# Set loop variables as these are easier to pass then $_.
$azureSQLDatabaseName = $_.dbname

# Execute SQL Query Against Azure SQL
$azureSQLServerName = $azureSQLServerName + ".database.windows.net"
$Cred = Get-AutomationPSCredential -Name $azureSQLCred
$SQLOutput = $(Invoke-Sqlcmd -ServerInstance $azureSQLServerName -Username $Cred.UserName -Password $Cred.GetNetworkCredential().Password -Database $azureSQLDatabaseName -Query "SELECT * FROM INFORMATION_SCHEMA.TABLES " -QueryTimeout 65535 -ConnectionTimeout 60 -Verbose) 4>&1
Write-Output $SQLOutput
}
4

3 回答 3

2

您可以尝试将每个连接作为一个powershell 作业。这解决了我前段时间遇到的一个非常相似的问题。如果您想阅读说明,Send-MailMessage 会在使用附件时关闭每第二个连接。基本上,如果您无法使用 .Close() 方法,您可以通过终止每次运行的整个会话来强制关闭连接。在理想情况下,cmdlet 会为您处理所有这些,但并非所有内容都是完美创建的。

# Loop through the datatable using the values per column 
$table | ForEach-Object {

# Set loop variables as these are easier to pass then $_.
$azureSQLDatabaseName = $_.dbname

# Execute SQL Query Against Azure SQL
$azureSQLServerName = $azureSQLServerName + ".database.windows.net"
$Cred = Get-AutomationPSCredential -Name $azureSQLCred

# Pass in the needed parameters via -ArgumentList and start the job.
Start-Job -ScriptBlock { Write-Output $(Invoke-Sqlcmd -ServerInstance $args[0] -Username $args[1].UserName -Password $args[1].GetNetworkCredential().Password -Database $args[0] -Query "SELECT * FROM INFORMATION_SCHEMA.TABLES " -QueryTimeout 65535 -ConnectionTimeout 60 -Verbose) 4>&1 } -ArgumentList $azureSQLServerName, $Cred | Wait-Job | Receive-Job

}

这是未经测试的,因为我没有要连接的服务器,但也许通过一些工作你可以从中做出一些事情。

于 2018-05-16T16:19:07.380 回答
1

我以前在使用 azure sql 的数据库时遇到了同样的问题。你可以试试这个

1.创建自动化帐户

New-AzureRmAutomationAccount -ResourceGroupName $resourceGroupName -Name $automationAccountName -Location $location

2.设置要使用的自动化帐户

Set-AzureRmAutomationAccount -Name $automationAccountName -ResourceGroupName $resourceGroupName

3. 创建/导入 Runbook

在这里,我们已经准备好运行手册,因此我们将其导入。这是运行手册代码

workflow runbookNameValue
{
    inlinescript
    {
        $MasterDatabaseConnection = New-Object System.Data.SqlClient.SqlConnection
        $MasterDatabaseConnection.ConnectionString = "ConnectionStringValue"

        # Open connection to Master DB
        $MasterDatabaseConnection.Open()

        # Create command
        $MasterDatabaseCommand = New-Object System.Data.SqlClient.SqlCommand
        $MasterDatabaseCommand.Connection = $MasterDatabaseConnection
        $MasterDatabaseCommand.CommandText = "Exec stored procedure"

        # Execute the query
        $MasterDatabaseCommand.ExecuteNonQuery()

        # Close connection to Master DB
        $MasterDatabaseConnection.Close() 
    }
}

4. 进口

Import-AzureRMAutomationRunbook -Name $runBookName -Path $scriptPath -ResourceGroupName $resourceGroupName -AutomationAccountName $automationAccountName -Type PowerShell

我希望这有帮助。而不是使用 Invoke-Sqlcmd 使用 $MasterDatabaseCommand.ExecuteNonQuery()我在运行手册中提供的类似内容。它会工作

于 2018-05-21T05:00:00.530 回答
1

似乎您在循环内附加到服务器.database.windows.net名称。我想这就是为什么它只适用于第一次迭代。

只需移动这一行:

$azureSQLServerName = $azureSQLServerName + ".database.windows.net"

在此行之前:

$table | ForEach-Object {
于 2018-05-19T10:54:30.730 回答