如何读取SQL表行作为PowerShell参数,批量执行Azure SQL脚本
在Azure PowerShell Runbook中批量执行SQL脚本(从SQL表读取目标库信息)
我在Azure环境中通过PowerShell Runbook,要在数百个Azure SQL数据库里运行存储容器中的多个.sql文件。需要从SQL Server的一张表中读取Servername和Databasename传入脚本执行,同时过滤掉Status为Skip的行。该表结构和数据如下:
| Servername | Databasename | Status |
|---|---|---|
| Server-01 | DB-01 | Process |
| Server-01 | DB-02 | Skip |
| Server-02 | DB-03 | Process |
当前已有脚本可读取容器内文件并在指定库执行,但目标库为硬编码,需修改为从表中读取:
# Get the blob container $blobs = Get-AzStorageContainer -Name $containerName -Context $ctx | Get-AzStorageBlob # Download the blob content to localhost and execute each one foreach ($blob in $blobs) { $file = Get-AzStorageBlobContent -Container $containerName -Blob $blob.Name -Destination "." -Context $ctx Write-Output ("Processing file :" + $file.Name) $query = Get-Content -Path $file.Name Invoke-Sqlcmd -ServerInstance "Server-01.database.windows.net" -Database "DB-01" -Query $query -AccessToken $access_token Write-Output ("This file is executed :" + $file.Name) }
实现方案
1. 核心思路
- 先连接存储目标库列表的SQL Server,查询过滤出
Status = 'Process'的记录,拼接Azure SQL完整实例名 - 嵌套循环遍历目标库和SQL文件,逐个库执行所有脚本
修改后的完整脚本
# 1. 连接到存储目标库列表的SQL Server,获取需处理的库信息 # 替换为你的列表所在SQL实例、数据库名、表名及身份验证信息 $listServerInstance = "Your-List-Server.database.windows.net" $listDatabase = "Your-List-DB" $listAccessToken = "Your-Access-Token-For-List-DB" # 也可使用SQL身份验证:-Username "xxx" -Password "xxx" # 查询获取目标库,过滤Status=Process并拼接完整实例地址 $targetDatabases = Invoke-Sqlcmd -ServerInstance $listServerInstance ` -Database $listDatabase ` -Query "SELECT CONCAT(Servername, '.database.windows.net') AS ServerInstance, Databasename FROM YourTableName WHERE Status = 'Process'" ` -AccessToken $listAccessToken # 2. 获取容器中的SQL文件 $blobs = Get-AzStorageContainer -Name $containerName -Context $ctx | Get-AzStorageBlob # 3. 遍历每个目标库,执行所有SQL文件 foreach ($db in $targetDatabases) { $serverInstance = $db.ServerInstance $databaseName = $db.Databasename Write-Output "===== 开始处理数据库:$serverInstance/$databaseName =====" foreach ($blob in $blobs) { # 下载SQL文件到本地,-Force覆盖同名文件 $file = Get-AzStorageBlobContent -Container $containerName -Blob $blob.Name -Destination "." -Context $ctx -Force Write-Output "正在处理文件:$($file.Name)" # 读取SQL内容(-Raw避免换行导致的语法错误) $query = Get-Content -Path $file.Name -Raw try { # 执行SQL脚本 Invoke-Sqlcmd -ServerInstance $serverInstance ` -Database $databaseName ` -Query $query ` -AccessToken $access_token ` -ErrorAction Stop Write-Output "文件 $($file.Name) 在 $serverInstance/$databaseName 执行成功" } catch { Write-Error "文件 $($file.Name) 在 $serverInstance/$databaseName 执行失败:$_" } # 删除本地临时文件 Remove-Item -Path $file.Name -Force -ErrorAction SilentlyContinue } Write-Output "===== 数据库 $serverInstance/$databaseName 处理完成 =====" }
关键说明
- 身份验证:根据实际场景选择AccessToken、SQL身份验证或托管身份,确保拥有列表库和目标库的访问权限
- 文件处理:用
-Raw读取SQL文件避免多行拆分问题,下载时加-Force覆盖旧文件,执行后删除临时文件释放空间 - 错误捕获:通过
try/catch捕获执行异常,便于排查故障 - 循环顺序:若脚本为库定制,可调整循环顺序为先文件后库;通用脚本推荐先库后文件的执行逻辑
内容的提问来源于stack exchange,提问作者Strayda
相关产品推荐
相关产品推荐

