Found plenty of examples online how to do the following in powershell:
Get-ChildItem $databaseFolder -Filter *.sql -Recurse | ForEach-Object { sqlcmd -S $databaseServer -d $databaseName -E -i $_.FullName }
However, I’d like to group this under one single transaction so if one of the sql files fails, then everything is rolled back.
One alternative that I am also trying is to put together all the file contents in to a full script variable:
foreach( $file in Get-ChildItem -path $databaseFolder -Filter *.sql | sort-object )
{
Get-Content $file.fullName | Foreach-Object { $fullSqlScript = $fullSqlScript + $_ + "`n" } ;
}
And then execute that in the end like so:
invoke-sqlcmd -ServerInstance $databaseServer -Database $databaseName -Query $fullSqlScript | format-table | out-file -filePath $outFile
The $fullSqlScript would also have the following inserted at the top:
:On Error Exit
SET XACT_ABORT ON
GO
Begin Transaction
and end:
IF XACT_STATE() = 1
BEGIN
PRINT 'Committing Transaction...'
COMMIT TRANSACTION
END
ELSE IF XACT_STATE() = -1
BEGIN
PRINT 'Scripts Failed... Rolling back'
ROLLBACK TRAN
END
However, as soon as I make an intentional sql script fail then the entire database is locked up like the transaction cannot be rolled back. I’m assuming this has something to do with invoke-sqlcmd being used in a powershell script environment rather than sqlcmd from windows command prompt?
I believe it has been solved.
After reading the following article about having the On Error Exit only having ability to be executed using sqlcmd, I definitely had doubts about the powershell invoke-sqlcmd.
Here’s some documentation I found here that I think may have something to do with it:
http://technet.microsoft.com/en-us/library/cc281720.aspx
In particular the following:
*
*
In the end, I am still using the strategy of having to read the contents of each file and then having the:
at the top of the script that is finally written to an output file containing all the other sql from other files.
Then, I do the following to invoke the actual sqlcmd:
This seems to work just fine and everything does get rolled back 🙂
If anyone can think of a better solution please let me know!