azure SQL 带副本的数据库导入

azure SQL DB import with copy

我正在开发一个 ARM 模板,该模板将要求以逗号分隔的数据库名称列表,然后使用 copyIndex 函数创建它们。这方面工作很好,但我的解决方案的下一步不是。接下来我想做的是为每个数据库导入一个 .bacpac 文件,以便在完成后可以使用。

验证错误表明问题出在 Import 资源 dependsOn 中的 concat 函数。我已经用几种不同的方法对其进行了测试,但看不出哪里错了。

我看到的确切错误消息是....

Unable to process template language expressions for resource '/subscriptions/xxxxxx-xxxxx-xxxxxx-xxxxx/resourceGroups/testGroup/providers/Microsoft.Sql/servers/testsql/databases/CustomersDB/extensions/import' at line '858' and column '10'. 'The provided parameters for language function 'concat' are invalid. Either all or none of the parameters must be an array.

**添加了整个模板

"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
  "type": "string",
  "defaultValue": "centralus"
},
"sqlAdminUsername": {
  "type": "string"
},
"sqlAdminPassword": {
  "type": "securestring"
},
"sqlServerName": {
  "type": "string"
},
"sqlDatabaseNames": {
  "type": "array",
  "defaultValue": [
    "CustomersDB",
    "WideWorldImporters-Standard"
  ]
},
"sqlEdition": {
  "type": "string",
  "defaultValue": "Standard"
},
"sqlRequestedServiceObjectiveName": {
  "type": "string",
  "defaultValue": "S2"
},
"sqlMaxSizeBytes": {
  "type": "string",
  "defaultValue": "268435456000"
},
"publicIP": {
  "type": "string"
},
"_artifactsLocationSasToken": {
  "type": "securestring"
},
"_artifactsLocation": {
  "type": "string"
}
},
"variables": {
"storageKeyType": "SharedAccessKey",
"collation": "SQL_Latin1_General_CP1_CI_AS"
},
"resources": [
  {
    "name": "[parameters('sqlServerName')]",
    "type": "Microsoft.Sql/servers",
    "apiVersion": "2014-04-01-preview",
    "location": "[parameters('location')]",
    "properties": {
      "administratorLogin": "[parameters('sqlAdminUsername')]",
      "administratorLoginPassword": "[parameters('sqlAdminPassword')]",
      "version": "12.0"
    },
    "resources": [
      {
        "name": "AllowAllWindowsAzureIps",
        "type": "firewallrules",
        "apiVersion": "2014-04-01-preview",
        "location": "[parameters('location')]",
        "dependsOn": [
          "[concat('Microsoft.Sql/servers/', parameters('sqlServerName'))]"
        ],
        "properties": {
          "endIpAddress": "0.0.0.0",
          "startIpAddress": "0.0.0.0"
        }
      },
      {
        "name": "Allow_Remote_SSMS",
        "type": "firewallrules",
        "apiVersion": "2014-04-01-preview",
        "location": "[parameters('location')]",
        "dependsOn": [
          "[concat('Microsoft.Sql/servers/', parameters('sqlServerName'))]"
        ],
        "properties": {
          "startIpAddress": "[parameters('publicIP')]",
          "endIpAddress": "[parameters('publicIP')]"
        }
      }
    ]
  },
  {
    "name": "[concat(parameters('sqlServerName'), '/', parameters('sqlDatabaseNames')[copyIndex()])]",
    "type": "Microsoft.Sql/servers/databases",
    "location": "[parameters('location')]",
    "apiVersion": "2014-04-01-preview",
    "copy": {
      "count": "[length(parameters('sqlDatabaseNames'))]",
      "name": "sql-copy"
    },
    "dependsOn": [ "[resourceId('Microsoft.Sql/servers/', parameters('sqlServerName'))]" ],
    "properties": {
      "collation": "[variables('collation')]",
      "edition": "[parameters('sqlEdition')]",
      "maxSizeBytes": "[parameters('sqlMaxSizeBytes')]",
      "requestedServiceObjectiveName": "[parameters('sqlRequestedServiceObjectiveName')]"
    }
  },
  {
    "name": "[concat(parameters('sqlServerName'), '/', parameters('sqlDatabaseNames')[copyIndex()],'/','import')]",
    "type": "Microsoft.Sql/servers/databases/extensions",
    "apiVersion": "2014-04-01-preview",
    "dependsOn": [ "sql-copy" ],
    "copy": {
      "name": "sql-import",
      "count": "[length(parameters('sqlDatabaseNames'))]"
    },
    "properties": {
      "storageKeyType": "[variables('storageKeyType')]",
      "storageKey": "[parameters('_artifactsLocationSasToken')]",
      "storageUri": "[concat(parameters('_artifactsLocation'), '/', 'databaseFiles', '/', parameters('sqlDatabaseNames'), '.bacpac')]",
      "administratorLogin": "[parameters('sqlAdminUsername')]",
      "administratorLoginPassword": "[parameters('sqlAdminPassword')]",
      "operationMode": "Import"
    }
  }
],
}

据我所知,我们不能在嵌套资源中使用copyindex函数。

如果你运行你的手臂模板,你会遇到这个错误:

Copying nested resources is not supported. Please see https://aka.ms/arm-copy/#looping-on-a-nested-resource for usage details.'.

所以我建议你将嵌套资源作为根资源移动到arm模板中。然后你可以使用copyindex.

更多细节,您可以参考下面的arm模板:

注意:将参数 orb 替换为您的数据库名称。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "brandosqlAdminLogin": {
      "type": "string",
      "minLength": 1
    },
    "brandosqlAdminLoginPassword": {
      "type": "string"
    },
    "org": {
      "type": "array",
      "defaultValue": [
        "contoso",
        "fabrikam",
        "coho"
      ]
    },
    "copydatabaseCollation": {
      "type": "string",
      "minLength": 1,
      "defaultValue": "SQL_Latin1_General_CP1_CI_AS"
    },
    "copydatabaseEdition": {
      "type": "string",
      "defaultValue": "Basic",
      "allowedValues": [
        "Basic",
        "Standard",
        "Premium"
      ]
    },
    "copydatabaseRequestedServiceObjectiveName": {
      "type": "string",
      "defaultValue": "Basic",
      "allowedValues": [
        "Basic",
        "S0",
        "S1",
        "S2",
        "P1",
        "P2",
        "P3"
      ],
      "metadata": {
        "description": "Describes the performance level for Edition"
      }
    },
    "copy2StorageKeyType": {
      "type": "string",
      "minLength": 1
    },
    "copy2StorageKey": {
      "type": "string"
    },
    "copy2StorageUri": {
      "type": "string",
      "minLength": 1
    },
    "copy2AdministratorLogin": {
      "type": "string",
      "minLength": 1
    },
    "copy2AdministratorLoginPassword": {
      "type": "string"
    },
    "serverDatabaseName": {
      "type": "array",
      "defaultValue": [
        "brandoimprottest/contoso",
        "brandoimprottest/fabrikam",
        "brandoimprottest/coho"
      ]
    },

    "copysqldatabase2Collation": {
      "type": "string",
      "minLength": 1,
      "defaultValue": "SQL_Latin1_General_CP1_CI_AS"
    },
    "copysqldatabase2Edition": {
      "type": "string",
      "defaultValue": "Basic",
      "allowedValues": [
        "Basic",
        "Standard",
        "Premium"
      ]
    },
    "copysqldatabase2RequestedServiceObjectiveName": {
      "type": "string",
      "defaultValue": "Basic",
      "allowedValues": [
        "Basic",
        "S0",
        "S1",
        "S2",
        "P1",
        "P2",
        "P3"
      ],
      "metadata": {
        "description": "Describes the performance level for Edition"
      }
    }

  },
  "variables": {
    "brandosqlName": "brandoimprottest"
    },
  "resources": [
    {
      "name": "[variables('brandosqlName')]",
      "type": "Microsoft.Sql/servers",
      "location": "[resourceGroup().location]",
      "apiVersion": "2014-04-01-preview",
      "dependsOn": [],
      "tags": {
        "displayName": "brandosql"
      },
      "properties": {
        "administratorLogin": "[parameters('brandosqlAdminLogin')]",
        "administratorLoginPassword": "[parameters('brandosqlAdminLoginPassword')]"
      },
      "resources": [
        {
          "name": "AllowAllWindowsAzureIps",
          "type": "firewallrules",
          "location": "[resourceGroup().location]",
          "apiVersion": "2014-04-01-preview",
          "dependsOn": [
            "[resourceId('Microsoft.Sql/servers', variables('brandosqlName'))]"
          ],
          "properties": {
            "startIpAddress": "0.0.0.0",
            "endIpAddress": "0.0.0.0"
          }
        }
      ]
    },
    {
      "name": "[concat(variables('brandosqlName'), '/', parameters('org')[copyIndex()])]",
      "type": "Microsoft.Sql/servers/databases",
      "location": "[resourceGroup().location]",
      "apiVersion": "2014-04-01-preview",
      "copy": {
        "count": 3,
        "name": "sql-copy"
      },
      "dependsOn": [ "[resourceId('Microsoft.Sql/servers', variables('brandosqlName'))]" ],
      "tags": {
        "displayName": "copysqldatabase2"
      },
      "properties": {
        "collation": "[parameters('copysqldatabase2Collation')]",
        "edition": "[parameters('copysqldatabase2Edition')]",
        "maxSizeBytes": "1073741824",
        "requestedServiceObjectiveName": "[parameters('copysqldatabase2RequestedServiceObjectiveName')]"
      }
    },
    {
      "name": "[concat(variables('brandosqlName'), '/', parameters('org')[copyIndex()],'/','aaaa')]",
      "type": "Microsoft.Sql/servers/databases/extensions",
      "apiVersion": "2014-04-01-preview",
      "dependsOn": [ "sql-copy" ],
      "tags": {
        "displayName": "copy3"
      },
      "copy": {
        "name": "sql-copy2",
        "count": 3
      },
      "properties": {
        "storageKeyType": "[parameters('copy2StorageKeyType')]",
        "storageKey": "[parameters('copy2StorageKey')]",
        "storageUri": "[parameters('copy2StorageUri')]",
        "administratorLogin": "[parameters('copy2AdministratorLogin')]",
        "administratorLoginPassword": "[parameters('copy2AdministratorLoginPassword')]",
        "operationMode": "Import"
      }
    }
  ],
  "outputs": {}
}

结果:


我也测试了你的模板,我发现你在导入扩展中的存储 url 有问题。我用主存储密钥和 url 更改了它。效果不错。

模板:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "eastasia"
    },
    "sqlAdminUsername": {
      "type": "string"
    },
    "sqlAdminPassword": {
      "type": "string"
    },
    "sqlServerName": {
      "type": "string"
    },
    "sqlDatabaseNames": {
      "type": "array",
      "defaultValue": [
        "CustomersDB",
        "WideWorldImporters-Standard"
      ]
    },
    "sqlEdition": {
      "type": "string",
      "defaultValue": "Standard"
    },
    "sqlRequestedServiceObjectiveName": {
      "type": "string",
      "defaultValue": "S2"
    },
    "sqlMaxSizeBytes": {
      "type": "string",
      "defaultValue": "268435456000"
    },
    "publicIP": {
      "type": "string"
    },
    "copy2StorageKeyType": {
      "type": "string",
      "minLength": 1
    },
    "copy2StorageKey": {
      "type": "string"
    },
    "copy2StorageUri": {
      "type": "string",
      "minLength": 1
    }

  },
  "variables": {
    "storageKeyType": "SharedAccessKey",
    "collation": "SQL_Latin1_General_CP1_CI_AS"
  },
  "resources": [
    {
      "name": "[parameters('sqlServerName')]",
      "type": "Microsoft.Sql/servers",
      "apiVersion": "2014-04-01-preview",
      "location": "[parameters('location')]",
      "properties": {
        "administratorLogin": "[parameters('sqlAdminUsername')]",
        "administratorLoginPassword": "[parameters('sqlAdminPassword')]",
        "version": "12.0"
      },
      "resources": [
        {
          "name": "AllowAllWindowsAzureIps",
          "type": "firewallrules",
          "apiVersion": "2014-04-01-preview",
          "location": "[parameters('location')]",
          "dependsOn": [
            "[concat('Microsoft.Sql/servers/', parameters('sqlServerName'))]"
          ],
          "properties": {
            "endIpAddress": "0.0.0.0",
            "startIpAddress": "0.0.0.0"
          }
        },
        {
          "name": "Allow_Remote_SSMS",
          "type": "firewallrules",
          "apiVersion": "2014-04-01-preview",
          "location": "[parameters('location')]",
          "dependsOn": [
            "[concat('Microsoft.Sql/servers/', parameters('sqlServerName'))]"
          ],
          "properties": {
            "startIpAddress": "[parameters('publicIP')]",
            "endIpAddress": "[parameters('publicIP')]"
          }
        }
      ]
    },
    {
      "name": "[concat(parameters('sqlServerName'), '/', parameters('sqlDatabaseNames')[copyIndex()])]",
      "type": "Microsoft.Sql/servers/databases",
      "location": "[parameters('location')]",
      "apiVersion": "2014-04-01-preview",
      "copy": {
        "count": "[length(parameters('sqlDatabaseNames'))]",
        "name": "sql-copy"
      },
      "dependsOn": [ "[resourceId('Microsoft.Sql/servers/', parameters('sqlServerName'))]" ],
      "properties": {
        "collation": "[variables('collation')]",
        "edition": "[parameters('sqlEdition')]",
        "maxSizeBytes": "[parameters('sqlMaxSizeBytes')]",
        "requestedServiceObjectiveName": "[parameters('sqlRequestedServiceObjectiveName')]"
      }
    },
    {
      "name": "[concat(parameters('sqlServerName'), '/', parameters('sqlDatabaseNames')[copyIndex()],'/','import')]",
      "type": "Microsoft.Sql/servers/databases/extensions",
      "apiVersion": "2014-04-01-preview",
      "dependsOn": [ "sql-copy" ],
      "copy": {
        "name": "sql-import",
        "count": "[length(parameters('sqlDatabaseNames'))]"
      },
      "properties": {
        "storageKeyType": "[parameters('copy2StorageKeyType')]",
        "storageKey": "[parameters('copy2StorageKey')]",
        "storageUri": "[parameters('copy2StorageUri')]",
        "administratorLogin": "[parameters('sqlAdminUsername')]",
        "administratorLoginPassword": "[parameters('sqlAdminPassword')]",
        "operationMode": "Import"
      }
    }
  ]
}

结果: