I’m creating a set of databases on a SQL Server 2008R2 instance using powershell, like this:
foreach ($database in $databases) {
# Create DB
$db = New-Object Microsoft.SqlServer.Management.SMO.Database
$db.Parent = Get-Item "SQLSERVER:\SQL\$DBServer\$Instance"
$db.Name = $database
$db.Create()
#
# Create tables, fill in data, etc
#
}
Here I’m assuming that none of the databases to be created already exist. If it turns out that one does, I want to abort and rollback. In SQL I would just wrap this in a BEGIN TRAN and ROLLBACK or COMMIT, but can I do this in Powershell? There is a cmdlet Start-Transaction, but it requires support from the commands used in the transactions, and $db.Create() does not.
Is there a way in the SMO object to do transactions? I could of course just check all the databases in advance, but the entire script is quite complicated, and I feel it would be more understandable if I can have the logic closer to the creation.
You couldn’t wrap this in SQL in a transaction either, since
CREATE DATABASEcannot be enrolled in a transaction:So the capability cannot be achieved in PS, SMO nor any other way. In lack of transactions you need to handle errors carefully. It would be very difficult to achieve atomic behavior for ‘all or none’ databases to be created. If you hit an error, you are not guaranteed that you can drop the databases already created.
If possible, is better to thrive for idempotency: if you run the script and hit an error on database 5, next time you run it it skips databases 1-4 which were already created. Or, alternatively, it drops the databases already created if exist and create them again (this is risky, as the script may end up dropping the wrong DBs due to operator error).