Azure DB & Schema Change Tracking - azure

I'm new to Azure and I have been asked to generate a daily report of added/changed databases, table or columns in Azure SQL Server. Specifically, we want to know when new datbases are created, new tables are added or existing ones altered and the same for columns. In non-Azure SQL Server you can use the Schema Changes History in standard reports but this is not available in Azure.
I have seen some suggestions you can do this with Extended Events but I've not found any resources to show how this can be done. Any help would be appreciated.

DDL Triggers can really help you to keep track schema changes on your Azure SQL Database. Below is an example:
CREATE TRIGGER safety
ON DATABASE
FOR DROP_TABLE, ALTER_TABLE
AS
PRINT 'Save change on a log'
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)');
Database Auditing can help with schema changes and dropped objects. Below an example:
Set-AzureRmSqlDatabaseAuditing `
-State Enabled `
-ResourceGroupName "resourcegroupname" `
-ServerName "ssqlinstancename" ` #ssqlinstancename.database.windows.net
-StorageAccountName "strageaccountname" `
-DatabaseName "dbname" `
-AuditActionGroup 'SCHEMA_OBJECT_CHANGE_GROUP' `
-RetentionInDays 8 `
-AuditAction "DELETE ON schema::dbo BY [public]"
If you want to track DML operations also, you can use Temporal Tables but Database Auditing can help also:
Set-AzureRmSqlDatabaseAuditing -ResourceGroupName "resourceGroup"
-ServerName "SQL Server Name" -DatabaseName "AdventureWorksLT"
-StorageAccountName "storageAccount"
-AuditActionGroup "SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP", "FAILED_DATABASE_AUTHENTICATION_GROUP", "BATCH_COMPLETED_GROUP"
-AuditAction "UPDATE ON database::[AdventureWorksLT] BY [public]"
-RetentionInDays 60

Related

Move Azure Synapse DB Between Servers

I have 2 SQL servers under the same subscription in azure, both have an azure synapse DB on them. I want to move/copy one of the synapse DB's to the other server. I cannot find any documentation to do this online, all the stuff I have found refers to a normal SQL DB and the copy TSQL or the method doesn't seem to work. Can anyone refer me to an article explaining how I do this, or explain how I do this in azure?
Kind Regards
Glyn
The simplest way to do this is going to be through restore points, similar to how you might do it with a backup file in SQL Server. You can create a restore point either in the portal or via Powershell.
$SubscriptionName="<YourSubscriptionName>"
$ResourceGroupName="<YourResourceGroupName>"
$ServerName="<YourServerNameWithoutURLSuffixSeeNote>" # Without database.windows.net
$DatabaseName="<YourDatabaseName>"
$Label = "<YourRestorePointLabel>"
Connect-AzAccount
Get-AzSubscription
Select-AzSubscription -SubscriptionName $SubscriptionName
# Create a restore point of the original database
New-AzSqlDatabaseRestorePoint -ResourceGroupName $ResourceGroupName -ServerName $ServerName -DatabaseName $DatabaseName -RestorePointLabel $Label
Once the point is created it is possible to restore it to a different server, again using the portal or via Powershell script. They don't need to be in the same resource group for this to work.
$SubscriptionName="<YourSubscriptionName>"
$ResourceGroupName="<YourResourceGroupName>"
$ServerName="<YourServerNameWithoutURLSuffixSeeNote>" # Without database.windows.net
#$TargetResourceGroupName="<YourTargetResourceGroupName>" # uncomment to restore to a different server.
#$TargetServerName="<YourtargetServerNameWithoutURLSuffixSeeNote>"
$DatabaseName="<YourDatabaseName>"
$NewDatabaseName="<YourDatabaseName>"
Connect-AzAccount
Get-AzSubscription
Select-AzSubscription -SubscriptionName $SubscriptionName
# Or list all restore points
Get-AzSqlDatabaseRestorePoint -ResourceGroupName $ResourceGroupName -ServerName $ServerName -DatabaseName $DatabaseName
# Get the specific database to restore
$Database = Get-AzSqlDatabase -ResourceGroupName $ResourceGroupName -ServerName $ServerName -DatabaseName $DatabaseName
# Pick desired restore point using RestorePointCreationDate "xx/xx/xxxx xx:xx:xx xx"
$PointInTime="<RestorePointCreationDate>"
# Restore database from a restore point
$RestoredDatabase = Restore-AzSqlDatabase –FromPointInTimeBackup –PointInTime $PointInTime -ResourceGroupName $Database.ResourceGroupName -ServerName $Database.ServerName -TargetDatabaseName $NewDatabaseName –ResourceId $Database.ResourceID
# Use the following command to restore to a different server
#$TargetResourceGroupName = $Database.ResourceGroupName # for restoring to different server in same resourcegroup
#$RestoredDatabase = Restore-AzSqlDatabase –FromPointInTimeBackup –PointInTime $PointInTime -ResourceGroupName $TargetResourceGroupName -ServerName $TargetServerName -TargetDatabaseName $NewDatabaseName –ResourceId $Database.ResourceID
# Verify the status of restored database
$RestoredDatabase.status
This doesn't cover things like server firewall settings, so if you want those to match you'll have to move that separately. The server is Azure SQL, so guides for migrating Azure SQL firewalls should also apply to Synapse dedicated pools.
If the number of tables is small, then the copy activity in Pipelines might be a good backup option, but since it requires one activity per table, setting it up for a large database will be significantly more complex than using restore points.

Check whether Azure SQL database has been fully removed

I am creating a simple Azure logic app that uses a function to:
Delete a slave database
Restore a copy of a master database (with the same name as the removed slave)
Remove Database
# Remove slave database
Remove-AzSqlDatabase `
-DatabaseName $RestoreDatabaseName `
-ServerName $ServerName `
-ResourceGroupName $ResourceGroupName
Write-Host "Removed slave database"
Restore PIT Backup of Master
# Restore database
Restore-AzSqlDatabase `
-FromPointInTimeBackup `
-PointInTime (Get-Date).AddMinutes(-2) `
-ResourceGroupName $ResourceGroupName `
-ServerName $ServerName `
-TargetDatabaseName $RestoreDatabaseName `
-ResourceId $Database.ResourceID `
-ElasticPoolName $ElasticPoolName
The issue i am having is that after removing the database, Azure still sees the database on the server and so i get the following error when restoring:
The destination database name 'Slave' already exists on the server
'server address'.
I cant find any way to check if this has been fully removed before starting the next function. Any help on how to achieve this would be greatly appreciated.
You can use Get-AzSqlDatabase to check if the DB is still in play.
Get-AzSqlDatabase -ResourceGroupName "ResourceGroup01" -ServerName "Server01" -DatabaseName "Database02"
Placing this in a loop with a sleep will give you a poll to check when the DB is finally gone for good and you can then resume your processing.
Start-Sleep -s 15
Make sure you have a circuit breaker in your logic to prevent and endless loop in the case of a failed deletion.
It may be easier to restore your DB with a new name to avoid the delay e.g. MyDb<yyyymmdd>
Or alternatively, use the Azure REST API from SQL DB delete.
DELETE https://management.azure.com/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SouthEastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb?api-version=2017-10-01-preview
and monitor the location response of the 204 Accepted to determine when the database has been completely removed. Azure Durable Functions give you a great monitor pattern you can use.

Clone azure SQL elastic database to non-elastic server in a different resource group

I'm trying to clone an existing Azure SQL DB that's in an elastic pool to a standard SQL server in a different resource group. Whenever I run (with Az Powershell)
Restore-AzSqlDatabase -FromPointInTimeBackup -PointInTime (Get-Date) -ResourceGroupName $TargetRGName -ServerName $TargetServerName -TargetDatabaseName $TargetDBName -ResourceId $Database.ResourceID,
I get the error Long running operation failed with status 'Failed'. Additional Info:'An unexpected error occured while processing the request.
According to my script, you use Point-in-time restoration to restore your database. But we can not use the way to restore a database on the different servers. For more details, please refer to https://learn.microsoft.com/en-us/azure/sql-database/sql-database-recovery-using-backups#point-in-time-restore.
So if you want to restore the database on the different server, I suggest you use geo-store. If we use it, we can restore a SQL database on any server in any Azure region from the most recent geo-replicated backups. For further information, you read the official document. Regarding how to implement it by powershell, please refer to the following script
Connect-AzAccount
# get geo backup
$GeoBackup = Get-AzSqlDatabaseGeoBackup -ResourceGroupName "ResourceGroup01" -ServerName "Server01" -DatabaseName "Database01"
#restore database
Restore-AzSqlDatabase -FromGeoBackup -ResourceGroupName "TargetResourceGroup" -ServerName "TargetServer" -TargetDatabaseName "RestoredDatabase" -ResourceId $GeoBackup.ResourceID -Edition "Standard" -RequestedServiceObjectiveName "S2"

Why can I not import data-tier application without access to all other databses?

I am attempting to backup and restore a database located in Azure SQL database via Azure blob storage. To do this I have ran Export Data-Tier Application... on the selected database and successfully stored it in a blob container as a BACPAC file. Now I am trying to do the reverse and Import Data-Tier Application... to check the backup process functions correctly, however I receive the following error:
'The server principal "username" is not able to access database
"Database A" under the current security context'
The database it is referencing is the first listed database in the server I am trying to create a new database in which I don't have permissions for, and each time I give myself permission to access the first it just moves down the list to the next one and blocks me again. I don't understand why I need permissions for database A, B, C... to create a new database which is a copy of D, especially when I have the db_manager role so shouldn't have an issue with database creation.
Does this error indicate I am doing something wrong with the backup import, or is this a known issue and I need to have permissions for all databases in a server where I wish to import a backup to?
Please update SQL Server Management Studio (SSMS) to the latest version and try to export/import with the latest SSMS.
You can achieve the same using Azure portal. Open the appropriate database server page and then, on the toolbar, select Import database.
Select the storage account and the container for the BACPAC file and then select the BACPAC file from which to import. In addition, specify the new database size (usually the same as origin) and provide the destination SQL Server credentials.
You can also try with PowerShell.
$importRequest = New-AzSqlDatabaseImport
-ResourceGroupName "<your_resource_group>" `
-ServerName "<your_server>" `
-DatabaseName "<your_database>" `
-DatabaseMaxSizeBytes "<database_size_in_bytes>" `
-StorageKeyType "StorageAccessKey" `
-StorageKey $(Get-AzStorageAccountKey -ResourceGroupName "<your_resource_group>" -StorageAccountName "<your_storage_account").Value[0] `
-StorageUri "https://myStorageAccount.blob.core.windows.net/importsample/sample.bacpac" `
-Edition "Standard" `
-ServiceObjectiveName "P6" `
-AdministratorLogin "<your_server_admin_account_user_id>" `
-AdministratorLoginPassword $(ConvertTo-SecureString -String "<your_server_admin_account_password>" -AsPlainText -Force)

Find who created table constraint in azure sql database

I have a azure sql database. Is it possible to find out who created the constraint on table? Or at least when it was added? If yes, how can I do that? Is there any scripts/tools for that purposes?
thanks in advance
Azure SQL has a feature named AUDITING. If enabled either on the server and/or database you can define a storage account to send the "Server Audit" and "Database Audit" logs to. In Azure storage, auditing logs are saved as a collection of blob files within a container named sqldbauditlogs. Use Power BI for example you can view audit log data.
If this features is not enabled your will struggle I think to find your user unless the database is accessed using Azure AD identities.
Please note Advanced Threat Detection will alert you on unusual access patterns. Least privilege approach to access is recommend.
Ref:
https://learn.microsoft.com/en-us/azure/sql-database/sql-database-auditing
Maybe you can use below query to find out when the constraint created from all the SQL execution records.
SELECT TOP 1000
QS.creation_time,
SUBSTRING(ST.text,(QS.statement_start_offset/2)+1,
((CASE QS.statement_end_offset WHEN -1 THEN DATALENGTH(st.text)
ELSE QS.statement_end_offset END - QS.statement_start_offset)/2) + 1
) AS statement_text,
ST.text,
QS.total_worker_time,
QS.last_worker_time,
QS.max_worker_time,
QS.min_worker_time
FROM
sys.dm_exec_query_stats QS
CROSS APPLY
sys.dm_exec_sql_text(QS.sql_handle) ST
WHERE ST.text LIKE '%constraint_name%'
ORDER BY
QS.creation_time DESC
This query will take a few time.
Hope this helps.
If you enable Azure SQL Auditing you can try the following using PowerShell.
Set-AzureRmSqlDatabaseAuditing `
-State Enabled `
-ResourceGroupName "resourcegroupname" `
-ServerName "ssqlinstancename" ` #ssqlinstancename.database.windows.net
-StorageAccountName "strageaccountname" `
-DatabaseName "dbname" `
-AuditActionGroup 'SCHEMA_OBJECT_CHANGE_GROUP' `
-RetentionInDays 8 `
-AuditAction "CREATE ON schema::dbo BY [public]"

Resources