Azure SQL 数据库部署

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019 | TFS 2018

注意

Microsoft Visual Studio Team Foundation Server 2018 和早期版本在命名方面具有以下差异:

  • 用于生成和发布的管道称为定义
  • 运行称为生成
  • 服务连接称为服务终结点
  • 阶段称为环境
  • 作业称为阶段

每次成功生成后,都可以自动将数据库更新部署到 Azure SQL数据库。

DACPAC

部署数据库的最简单方法是创建数据层包或 DACPAC。 DACPAC 可用于打包和部署架构更改和数据。 可以在 Visual Studio 中使用 SQL 数据库项目创建 DACPAC。

要将 DACPAC 部署到 Azure SQL 数据库,请将以下代码片段添加到 azure-pipelines.yml 文件。

- task: SqlAzureDacpacDeployment@1
  displayName: Execute Azure SQL : DacpacTask
  inputs:
    azureSubscription: '<Azure service connection>'
    ServerName: '<Database server name>'
    DatabaseName: '<Database name>'
    SqlUsername: '<SQL user name>'
    SqlPassword: '<SQL user password>'
    DacpacFile: '<Location of Dacpac file in $(Build.SourcesDirectory) after compilation>'

TFS 不支持 YAML。

另请参阅使用 Azure SQL 数据库部署任务时的身份验证信息

SQL 脚本

还可以使用 SQL 脚本(代替 DACPAC)来部署数据库。 下面是创建空数据库的 SQL 脚本的简单示例。

  USE [main]
  GO
  IF NOT EXISTS (SELECT name FROM main.sys.databases WHERE name = N'DatabaseExample')
  CREATE DATABASE [DatabaseExample]
  GO

要在管道中运行 SQL 脚本,需要 Azure PowerShell 脚本在 Azure 中创建和删除防火墙规则。 如果没有防火墙规则,Azure Pipelines 代理将无法与 Azure SQL 数据库通信。

以下 PowerShell 脚本创建两个规则。 可以将此脚本作为 SetAzureFirewallRule.ps1 签入存储库中。

ARM

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)
$agentIP = (New-Object net.webclient).downloadstring("https://api.ipify.org")
New-AzSqlServerFirewallRule -ResourceGroupName $ResourceGroupName -ServerName $ServerName -FirewallRuleName $FirewallRuleName -StartIPAddress $agentIp -EndIPAddress $agentIP

经典

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)

$ErrorActionPreference = 'Stop'

function New-AzureSQLServerFirewallRule {
  $agentIP = (New-Object net.webclient).downloadstring("https://api.ipify.org")
  New-AzureSqlDatabaseServerFirewallRule -StartIPAddress $agentIp -EndIPAddress $agentIp -RuleName $FirewallRuleName -ServerName $ServerName
}

function Update-AzureSQLServerFirewallRule{
  $agentIP= (New-Object net.webclient).downloadstring("https://api.ipify.org")
  Set-AzureSqlDatabaseServerFirewallRule -StartIPAddress $agentIp -EndIPAddress $agentIp -RuleName $FirewallRuleName -ServerName $ServerName
}

if ((Get-AzureSqlDatabaseServerFirewallRule -ServerName $ServerName -RuleName $FirewallRuleName -ErrorAction SilentlyContinue) -eq $null)
{
  New-AzureSQLServerFirewallRule
}
else
{
  Update-AzureSQLServerFirewallRule
}

以下 PowerShell 脚本将移除防火墙规则。 可以将此脚本作为 RemoveAzureFirewallRule.ps1 签入存储库中。

ARM

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)
Remove-AzSqlServerFirewallRule -ServerName $ServerName -FirewallRuleName $FirewallRuleName -ResourceGroupName $ResourceGroupName

经典

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)

$ErrorActionPreference = 'Stop'

if ((Get-AzureSqlDatabaseServerFirewallRule -ServerName $ServerName -RuleName $FirewallRuleName -ErrorAction SilentlyContinue))
{
  Remove-AzureSqlDatabaseServerFirewallRule -RuleName $FirewallRuleName -ServerName $ServerName
}

将以下内容添加到 azure-pipelines.yml 文件以运行 SQL 脚本。

variables:
  AzureSubscription: '<SERVICE_CONNECTION_NAME>'
  ResourceGroupName: '<RESOURCE_GROUP_NAME>'
  ServerName: '<DATABASE_SERVER_NAME>'
  ServerFqdn: '<DATABASE_FQDN>'
  DatabaseName: '<DATABASE_NAME>'
  AdminUser: '<DATABASE_USERNAME>'
  AdminPassword: '<DATABASE_PASSWORD>'
  SQLFile: '<LOCATION_OF_SQL_FILE_IN_$(Build.SourcesDirectory)>'

steps:
- task: AzurePowerShell@5
  displayName: 'Azure PowerShell script'
  inputs:
    azureSubscription: '$(AzureSubscription)'
    ScriptType: filePath
    ScriptPath: '$(Build.SourcesDirectory)\scripts\SetAzureFirewallRule.ps1'
    ScriptArguments: '-ServerName $(ServerName) -ResourceGroupName $(ResourceGroupName)'
    azurePowerShellVersion: LatestVersion

- task: CmdLine@2
  displayName: Run Sqlcmd
  inputs:
    filename: sqlcmd
    arguments: '-S $(ServerFqdn) -U $(AdminUser) -P $(AdminPassword) -d $(DatabaseName) -i $(SQLFile)'

- task: AzurePowerShell@5
  displayName: 'Azure PowerShell script'
  inputs:
    azureSubscription: '$(AzureSubscription)'
    ScriptType: filePath
    ScriptPath: '$(Build.SourcesDirectory)\scripts\RemoveAzureFirewallRule.ps1'
    ScriptArguments: '-ServerName $(ServerName) -ResourceGroupName $(ResourceGroupName)'
    azurePowerShellVersion: LatestVersion

TFS 不支持 YAML。

Azure 服务连接

Azure SQL 数据库部署任务是将数据库部署到 Azure 的主要机制。 与其他内置 Azure 任务一样,此任务需要 Azure 服务连接作为输入。 Azure 服务连接将存储用于从 Azure Pipelines 或 TFS 连接到 Azure 的凭据。

若要开始使用此任务,最简单的方法是以同时拥有 Azure DevOps 组织和 Azure 订阅的用户的身份登录。 在这种情况下,不必手动创建服务连接。 否则,若要了解如何创建 Azure 服务连接,请参阅创建 Azure 服务连接

若要了解如何创建 Azure 服务连接,请参阅创建 Azure 服务连接

按条件部署

可以选择仅将某些生成部署到 Azure 数据库。

若要在 YAML 中执行此操作,可使用以下方法之一:

  • 将部署步骤隔离到单独的作业中,并向该作业添加条件。
  • 向步骤添加条件。

以下示例演示如何使用步骤条件来仅部署源自主分支的生成。

- task: SqlAzureDacpacDeployment@1
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  inputs:
    azureSubscription: '<Azure service connection>'
    ServerName: '<Database server name>'
    DatabaseName: '<Database name>'
    SqlUsername: '<SQL user name>'
    SqlPassword: '<SQL user password>'
    DacpacFile: '<Location of Dacpac file in $(Build.SourcesDirectory) after compilation>'

若要详细了解条件,请参阅指定条件

TFS 不支持 YAML。

更多 SQL 操作

SQL Azure Dacpac 部署不一定能够支持你要执行的所有 SQL Server 操作。 在这些情况下,只需使用 PowerShell 或命令行脚本来运行所需的命令。 本部分介绍调用 SqlPackage.exe 工具的一些常见用例。 作为运行此工具的先决条件,必须使用自承载代理并在代理上安装该工具。

注意

如果从安装 SQLPackage 的文件夹执行 SQLPackage,则必须在路径前面加上 & 前缀,并将其用双引号括起来。

基本语法

<Path of SQLPackage.exe> <Arguments to SQLPackage.exe>

可以使用以下任一 SQL 脚本,具体取决于要执行的操作

提取

从活动的 SQL Server 或 Microsoft Azure SQL 数据库创建数据库快照 (.dacpac) 文件。

命令语法:

SqlPackage.exe /TargetFile:"<Target location of dacpac file>" /Action:Extract
/SourceServerName:"<ServerName>.database.windows.net"
/SourceDatabaseName:"<DatabaseName>" /SourceUser:"<Username>" /SourcePassword:"<Password>"

SqlPackage.exe /action:Extract /tf:"<Target location of dacpac file>"
/SourceConnectionString:"Data Source=ServerName;Initial Catalog=DatabaseName;Integrated Security=SSPI;Persist Security Info=False;"

示例:

SqlPackage.exe /TargetFile:"C:\temp\test.dacpac" /Action:Extract /SourceServerName:"DemoSqlServer.database.windows.net"
 /SourceDatabaseName:"Testdb" /SourceUser:"ajay" /SourcePassword:"SQLPassword"

帮助:

sqlpackage.exe /Action:Extract /?

发布

增量更新数据库架构以便匹配源 .dacpac 文件的架构。 如果数据库不存在于服务器上,则发布操作将创建该数据库。 否则,将更新现有数据库。

命令语法:

SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:Publish /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password> "

示例:

SqlPackage.exe /SourceFile:"E:\dacpac\ajyadb.dacpac" /Action:Publish /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb4" /TargetUser:"ajay" /TargetPassword:"SQLPassword"

帮助:

sqlpackage.exe /Action:Publish /?

导出

将活动数据库(包括数据库架构和用户数据)从 SQL Server 或 Microsoft Azure SQL 数据库导出到 BACPAC 包(.bacpac 文件)。

命令语法:

SqlPackage.exe /TargetFile:"<Target location for bacpac file>" /Action:Export /SourceServerName:"<ServerName>.database.windows.net"
/SourceDatabaseName:"<DatabaseName>" /SourceUser:"<Username>" /SourcePassword:"<Password>"

示例:

SqlPackage.exe /TargetFile:"C:\temp\test.bacpac" /Action:Export /SourceServerName:"DemoSqlServer.database.windows.net"
/SourceDatabaseName:"Testdb" /SourceUser:"ajay" /SourcePassword:"SQLPassword"

帮助:

sqlpackage.exe /Action:Export /?

导入

将架构和表数据从 BACPAC 包导入到 SQL Server 或 Microsoft Azure SQL 数据库的实例中的新用户数据库中。

命令语法:

SqlPackage.exe /SourceFile:"<Bacpac file location>" /Action:Import /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>"

示例:

SqlPackage.exe /SourceFile:"C:\temp\test.bacpac" /Action:Import /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword"

帮助:

sqlpackage.exe /Action:Import /?

DeployReport

创建将由发布操作完成的更改的 XML 报表。

命令语法:

SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:DeployReport /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output XML file path for deploy report>"

示例:

SqlPackage.exe /SourceFile:"E: \dacpac\ajyadb.dacpac" /Action:DeployReport /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\deployReport.xml" 

帮助:

sqlpackage.exe /Action:DeployReport /?

DriftReport

创建自注册数据库注册以来已对其做出的更改的 XML 报表。

命令语法:

SqlPackage.exe /Action:DriftReport /TargetServerName:"<ServerName>.database.windows.net" /TargetDatabaseName:"<DatabaseName>"
/TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output XML file path for drift report>"

示例:

SqlPackage.exe /Action:DriftReport /TargetServerName:"DemoSqlServer.database.windows.net" /TargetDatabaseName:"Testdb"
/TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\driftReport.xml"

帮助:

sqlpackage.exe /Action:DriftReport /?

脚本

创建 Transact-SQL 增量更新脚本,该脚本可更新目标的架构以匹配源的架构。

命令语法:

SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:Script /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output SQL script file path>"

示例:

SqlPackage.exe /Action:Script /SourceFile:"E:\dacpac\ajyadb.dacpac" /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\test.sql"
/Variables:StagingDatabase="Staging DB Variable value"

帮助:

sqlpackage.exe /Action:Script /?