I have an SSDT project with VS2015 and using SqlPackage.exe to generate deployment scripts and incremental update scripts. The database project contains post deployment scripts. here's how I generate the main script for DB installation:
sqlpackage.exe
/a:Script
/op:"database.sql"
/sf:"database.dacpac"
/tsn:"localhost"
/tdn:"MyDbName"
/p:CommentOutSetVarDeclarations="True"
/p:ScriptDatabaseCompatibility="True"
/p:IgnoreFileAndLogFilePath="True"
/p:IgnoreFilegroupPlacement="True"
/p:ScriptFileSize="True"
/p:PopulateFilesOnFilegroups="False"
This will output database.sql file which I run with sqlcmd.exe. the script file also contains all my post deployment scripts (Insert, Update, etc..)
Once I have a new version of the database, I create incremental update script from previously taken dacpac snapshot:
sqlpackage.exe
/a:Script
/op:"%migratePath%\%database%.!build!-%version%.sql"
/sf:"%snapshotPath%\%database%.%version%.dacpac"
/tf:"%snapshotPath%\%database%.!build!.dacpac"
/tdn:"MyDbName"
/p:CommentOutSetVarDeclarations="True"
/p:AllowIncompatiblePlatform="True"
/p:IgnorePermissions="True"
/p:IgnoreRoleMembership="True"
/p:ExcludeObjectTypes=Users;Credentials;Logins;Permissions;RoleMembership;ServerRoles;ServerRoleMembership;
this works fine, however, incremental update script does not contain metadata/reference data (e.g. e.g. list of countries, states, currencies, etc.).
Is there a way to tell SqlPackage to generate incremental script that contains the table reference data as well?
Related
I have a VS database project. When I make schema changes, I right click on the project and compare the schema. Then there are 2 options:
Update target
Generate script
In option 2, it generates sql script for all the schema changes. But this doesn't include the post deployment scripts. How to include the post deployment scripts (VS database project) as part of the generate scripts output?
I tried to generate the script by query because I want create easily and same settings. I checked MSdoc but there is no method.
I use SSMS v17.6, SQLServer2016(SP2) on WindowsServer2012 R2 Standard.
By the GUI, DB right click=>Task=>generate scripts=>select database objects and set some settings.
I want to generate by query.
You can follow below steps to automate the creation of a database.
First export the database as a dapac using Export Data Tier Application
Install SQLPackage.exe in the environment where you are planning to carry out the deployment. You can download sqlpackage.exe download path . It will be used to automate the generation of scripts from DACPAC.
Once you have the DACPAC of the database, you can publish the same to any environment. The caveat is, Sqlpackage.exe generates incremental script, comparing against the target datatbase. If you want complete CREATE script, then you can point against any empty database or system database like master to generate incremental CREATE scripts(here it will be complete database script, as target is empty database). The generated script will be present in the output path (here, it is C:\temp)
Note: we are setting parameter (DropObjectsNotInSource to false), to avoid generation of drop objects of the target database, which are
missing in source DACPAC.
"<Path>\SqlPackage.exe"
/Action:script
/SourceFile:“<Path>\Database.dacpac”
/TargetDatabaseName:master
/TargetServerName:"localhost"
/OutputPath:C:\temp
/p:DropObjectsNotInSource:false
UPDATE
I see that, now there is a tool mssql-scripter(currently in preview) to carry out the same activity of Generate Scripts wizard of SQL Server Management Studio. You can see about the tool here: https://github.com/Microsoft/mssql-scripter
I'm using Visual Studio 2013 with TFS, over SQL-Server 2012. Specifically I'm using SQL-Server Data Tools within VS for our SQL development, rather than within SQL-Server Management Studio.
In short, the Post-Deployment SQL script appears not to be executed by SQLPackage.
The specifics are: I have a VS SQL Database Project 'ADMIR', which has been developing over the last few weeks and gradually becoming more sophisticated both in terms of SQL and it's deployment. The database includes some dynamically generated tables and therefore I've introduced SQL Command Variables to reference two databases (one is the actual ADMIR database, the other a DB on the same Server). Therefore I've added Database References to dacpacs for these two DB's.
The ADMIR Project will Build fine.
There is also a Post-Deployment SQL script, and prior to the introduction of SQL Command Variables, this would also run fine and initialize various table data.
However, my understanding is that SQL Command Variables won't work with the VS/TFS Publish action, in that the Post-Deployment script is no longer being executed.
This is ok, as ultimately I want to script/automate the Publish/Deploy of the ADMIR Project and so I've moved to using SQLPackage to perform the Publish.
Again, this appears to work fine - My SQL Package batch command will execute and log errors/output (as applicable) and Publish my Build dacpac to the target Server successfully. However, it seems to completely ignore the Post-Deployment script. In addition, the output reports that the SQL Command Variables are not set.
These are the various scripts and configuration settings:
SQLPackage batch command:
::Publish the ADMIR database using the ADMIR.DEV.Publish.xml Profile.
"C:\Program Files (x86)\Microsoft SQL Server\120\DAC\bin\SqlPackage.exe"
/Action:Publish
/Profile:"C:\Source Control\ADMIR\ReleaseControl\ADMIR.DEV.publish.xml"
/SourceFile:"C:\Source Control\ADMIR\Build\ADMIR.dacpac"
2> "C:\Source Control\ADMIR\ReleaseControl\Publish_Error.txt"
> "C:\Source Control\ADMIR\ReleaseControl\Publish_Output.txt"
ADMIR.DEV.publish.xml Publishing Profile:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<IncludeCompositeObjects>True</IncludeCompositeObjects>
<TargetDatabaseName>ADMIR</TargetDatabaseName>
<DeployScriptFileName>ADMIR.sql</DeployScriptFileName>
<TargetConnectionString>Data Source=FOOBAR;Integrated Security=True;Pooling=False</TargetConnectionString>
<ProfileVersionNumber>1</ProfileVersionNumber>
</PropertyGroup>
<ItemGroup>
<SqlCmdVariable Include="ADMIRDatabaseName">
<Value>ADMIR</Value>
</SqlCmdVariable>
<SqlCmdVariable Include="XYZDatabaseName">
<Value>XYZDEV</Value>
</SqlCmdVariable>
</ItemGroup>
</Project>
Script.PostDeploy.sql (first few lines):
/* ADMIR Post-Deployment Script Template */
PRINT N'Post Deploy Script started:'+CAST(GETDATE() AS NVARCHAR(20))+N'.'
PRINT N'SQLCMD Variable $ADMIRDBName:'+[$(ADMIRDatabaseName)]+N'.'
PRINT N'SQLCMD Variable $XYZDBName:'+[$(XYZDatabaseName)]+N'.'
/* Purge existing data as we'll repopulate with what is required for a fresh deploy */
PRINT N'Purging existing table data...'
DELETE FROM [ADMIR].[Engine].[ProcessingStatus]
DELETE FROM [ADMIR].[Engine].[DataField]
DELETE FROM [ADMIR].[Engine].[DataKeyField]
...
...
When running a Build, I can see the ADMIR_Create.sql script does contain all the Post-Deploy statements. i.e. I can see the above lines of code in this file.
** ADMIR.sqlproj file contains the Post-Deploy scripts and the SQL Command Variables:**
<ItemGroup>
...
...
<PostDeploy Include="ReleaseControl\Script.PostDeploy.sql" />
</ItemGroup>
...
...
<ItemGroup>
<SqlCmdVariable Include="ADMIRDatabaseName">
<DefaultValue>ADMIR</DefaultValue>
<Value>$(SqlCmdVar__7)</Value>
</SqlCmdVariable>
<SqlCmdVariable Include="XYZDatabaseName">
<DefaultValue>XYZDEV</DefaultValue>
<Value>$(SqlCmdVar__6)</Value>
</SqlCmdVariable>
Publish log, Publish_Output.txt:
Publishing to database 'ADMIR' on server 'FOOBAR'.
Initializing deployment (Start)
*** The following SqlCmd variables are not defined in the target scripts: ADMIRDatabaseName XYZDatabaseName.
Initializing deployment (Complete)
Analyzing deployment plan (Start)
Analyzing deployment plan (Complete)
Updating database (Start)
Update complete.
Updating database (Complete)
Successfully published database.
So:
Why is the Post-Deployment script not being executed? I'm not seeing any logging information relating to it.
Why does the SQLPackage output log state that the SQL Command Variables are not defined, when they are in the Publish profile?
Possibly related to 2. Is the .sqlproj file correct in have the values of the SQL Command Variables as variables themselves e.g. $(SqlCmdVar__7)? where __6 & __7 coming from?
Thanks for any assistance!
I found that a new .sqlproj file created in Visual Studio 2017 did not include "default" Predeployment.sql or PostDeployment.sql files, so I added one manually.
Publishing did not execute the PostDeployment.sql because the file's Build Action was set to None. Changing the Build Action to PostDeploy fixed the issue.
As per my comment, the issue logged in MSDN Connect, appears to be cause. i.e. an SQLCMD variable with the same name as the dacpac for the database is resulting in the script not being executed. When I remove this reference, and change the related SQLCMD variables to literal values for the DB Name, then the project builds and the post-deploy script is executed as required.
We currently use TFS 2010 for our VS applications and our SQL code. For SQL we have every stored procedure stored in different text files e.g."spname.sql" and we alter these files and then apply them to the Dev server.
When it comes to testing we then do a branchcompare to compare the DEV branch to the UAT branch to get a list of the .sql files that are different.
Question is, is there a way to export out the files in the list from the dev branch so we can them apply all the SQL code that has changed to the UAT server?
(We do table alters / updates etc in a "rollout" type script).
Thanks
When you do a compare in Visual Studio (with SSDT), you can choose to create a script instead of deploying. Or you could use powershell Get-TfsItemHistory with -Version to get the file list and then use that list to get the source.
Does anyone know How to configure Visual Studio 2012 Database Project to Build a deployment .sql file package.
I'm attempting to not have to use the .dacpac as my only deployment option.
e.g. generate a .sql file of all database schema alters.
If you're trying to do this automatically, you'll want to use the SQLPackage command to generate a script. If you want to do this within the IDE, publish the database and choose the option to generate a script instead of publishing the changes.
I'll usually build the project first with msbuild. That will generate a dacpac against which I can run the SQLPackage command.
My batch file looks something like this:
msbuild .\MyDB\MyDB.sqlproj /t:build /p:Configuration="Local"
sqlpackage /a:DeployReport /tsn:FTPROD /sf:.\MyDB\sql\Local\MyDB.dacpac /pr:.\MyDB\Publish\Production.publish.xml /op:.\Release\MyDB-Production.xml
sqlpackage /a:script /tsn:DBServer /sf:.\MyDB\sql\Local\MyDB.dacpac /pr:.\MyDB\Publish\Production.publish.xml /op:.\Release\MyDB-Production.sql
The first line builds the project. The second creates a deploy report so I can easily see what's going to be changed. The last generates the script. Your paths may vary so you'll need to tweak as appropriate for your environment. You'll need to be able to access the database against which the script will be run in order to generate the script.