Why does Liquibase generateChangeLog generate an empty changelog file? - database

I'm using Liquibase to generate a DB scheme from existing H2 database.
I use the following:
liquibase --driver=org.h2.Driver --classpath=./h2-1.4.199.jar --changeLogFile=db.schema.sql --url="jdbc:h2:mem:testdb" --username=sa --password= --logLevel=debug generateChangeLog
So, absolutely default values in order to connect to the H2 instance. But the command above generates an empty changelog file (just some basic Liquibase headers).
I tried to use different urls (h2 in file), I tried to set different password and username, I even tried to define defaultSchemaName parameter, but still the same.
Liquibase maven plugin says: No changes found, nothing to do
Liquibase without maven plugin says: Liquibase command 'generateChangeLog' was executed successfully.
I also tried to put invalid credentials (username or password), but still the same.

generateChangeLog command exports data from the specified database. It means that such database should exist and be populated with some data.
There is no point to specify the in-memory embedded URL jdbc:h2:mem:testdb here. Each process have own memory and own in-memory databases. Liquibase will definitely see an empty database here inside its own memory.
You need to create a normal persistent database with your application and use its URL here. I strongly suggest you to specify the absolute database path (without file name extension) in the database URL to be sure that the same database will be used by your application and by Liquibase. Note that you can't use the embedded database by two applications at the same time without additional parameters (auto-server mode), so you need to close the database in your application before you'll launch Liquibase. As an alternative you can start the H2 Server process and use remote URLs or you can use the auto-server mode.
You can also append ;IFEXISTS=TRUE to the database URL for Liquibase only. It will prevent accidental silent creation of a new empty database in it.

Related

Access Build variables inside Pre and Post deployment scripts SSDT

I have just set up an SSDT project which I want to use to create local databases on the SQL server hosted locally on my machine.
I want to add some pre- and post- deployment SQL scripts for initialization and cleanups.
Since, the server and the database name can change, I have defined two build variables using the project properties each for the target server and target database.
However, I can't seem to access them inside the post deployment scripts.
The syntax below won't build the project -
use [$(TargetDatabaseName)]
This builds, but then fails while publishing -
use ['$(TargetDatabaseName)']
and the error says the ''myTargetDB'' doesn't exist (myTargetDB was passed as a value at the time of publishing)
This might be a trivial thing but I am just not able to get around it. I am on SQL server 2016 if that matters.
Make sure that you put both scripts in SQLCMD mode. See the image below surrounding with red.
Once your target variable is defined, see surrounding with blue in the image above, it can be safely used in the PostDeployment script, see the image below surrounding with blue.
If you have any questions, feel free to contact me.
There is a predefined variable, $(DatabaseName), for the name of the target database. You don't need to create your own; and even if you do, you would need to set the same value to both of them.
Not sure about the target server. In most cases, SQL scripts are generated with the assumption that connection to the correct server is already established. Sure, you can change the current server using something like :connect $(TargetServerName), but I think it will only lead to confusion (and I'm not sure it will work, actually).
The only exception I can think of is that you can't use SQLCMD variables to parameterise the logical/physical names of the database files - these have to be hardcoded.
All other variables, if declared in the project properties, should be accessible everywhere. Below is a fragment of a post deploy from one of my projects:
use [master];
go
print 'Switching database ownership to sa...';
GO
alter authorization on database::[$(DatabaseName)] to [sa];
go
use [$(DatabaseName)];
go
print 'Creating database master key...';
go
-- Create database master key
create master key encryption by password = '$(DMK_Key)';
go
print 'Running database setup...';
go
exec dbo.init_database;
go
It is possible, however, that you are trying to reference another database, located on a different server. If that's the case, you need to follow a different approach, namely: built a project for that remote database and add its DACPAC to the list of project references, using the Add database reference... menu. There, you will be able to specify variables for both the (linked) server and the database name.

SQL Compare Command-line does not synchronize database

In order to automate database synchronization using the SQL Compare command line; I have created a project to compare and deploy from my local database to a database in another server. Then I create a bat file. here is my bat file:
SET curdir=%~dp0
SET sqlcompare="C:\Program Files (x86)\Red Gate\SQL Compare 13\sqlcompare.exe"
%sqlcompare% /project:"%curdir%IcLoyalty.scp" /sync /include:Identical
The result of command is:
Registering data sources
Creating mappings
Comparing
Summarizing Project Selections
Retrieving migration scripts
Checking for identical databases
Creating SQL
Deploying changes (from DB1 to DB2)
When I check the destination database the changes does not apply. Consider that project work correctly when I open it with SQL Compare Application.
What I've missed in bat file?
It's possible that you had your selection (the checkboxes on the comparison results) deselected when you saved the project. Try selecting them all and resave the project.
This is from the documentation page.
"If you want to include or exclude objects from an existing project, you must modify your selection using the graphical user interface."

Database Project Over Multiple Environments?

How can you have environment specific table values in your database project and make sure that they only deploy to the environment you are deploying to with Release Management? We have been using Release Management for some time now, but only for .NET code. We are somewhat new to the DACPAC realm, but have found it easy to set up and use via release management. However, now we want to extend this capability to a table that has configuration variables per environment. How do we make this part of our database project and make sure that each environment has its own unique version of data?
Use SSDT for publishing the database schema and reference data; don't use it to manage environment settings.
Personally, I would (and have) run a secondary script post-deployment that configured environment-specific values. This is no different than putting the correct values in the web.config file of a web application post-deployment. It's something you manage within your deployment tool.
Ignoring the release management part to the question (because it depends what mode you use and whether you store configuration variables in RM etc) you can certainly pass in environment specific values into your dacpac execution (for use in 'postdeploy' data scripts) using sqlcmd variables defined in a tokenised publish file.
Broadly the process is:
Use standard sqlcmdvar syntax in your post deploy script e.g insert into table values '$(my_env_var)'
update the database project properties (sqlcmd tab) to include your new variable which ensures your dacpac expects a value when executed
Generate a publish.xml file (which should now include a node)
create a publish.release.xml file which contains transform instructions to update the value of your node to introduce a token e.g. ##my_env_var##
update your database project file(.sqlproj) to include instructions to transform publish.xml on build using the contents of publish.release.xml
Its quite long winded but what you get out of the above is a dacapac + tokenised publish file in your build output ready to be detokenised and executed by your deployment process..be that RM or any other tool.

Can I manage database using database project without knowing connection string?

I have created database project. I am able to upgrade my changes in my sql server. Now I have deploy the same changes on another environment. Also I dont want to change my previous data. I dont have to access that Sql server so I don`t know the connection string.
I have some options, like to deploy the .dacpac file or .sql script, but it first delete the database then creates new one. So that I loosing my data.
Please help me. If any option is there?
The options I see for this are:
Ask for a backup (or extract schema tables using task-->Generate scripts ion ssms) - restore this somewhere and use sqlpackage to generate a deployment script you can ask them to run
Ask them to run sqlpackage.exe and either generate a script or run it directly
Ask them for permissions so you can do it
If the database is being deleted then you have the option "CreateNewDatabase" set to true which would be bad in a production environment so remove it or set it to false!
If they run it or you ask for permissions, these are the minimum permissions you need to generate a script (to run the script you will probably need dbo):
https://the.agilesql.club/Blogs/Ed-Elliott/What-Permissions-Do-I-Need-To-Generate-A-Deploy-Script-With-SSDT (my blog)

How do I use the Flyway command-line client and flyway.conf to migrate multiple databases?

I started using flyway and its easy , but i only tried it with one Database.
setting flyway.url to that database
Using flyway migrate from command line to execute all the scripts.
This is the current Setting.
flyway.driver=net.sourceforge.jtds.jdbc.Driver
Jdbc url to use to connect to the database
flyway.url=jdbc:jtds:sqlserver://'databaseName'
User to use to connect to the database (default: <>)
flyway.user=user
Password to use to connect to the database (default: <>)
flyway.password=user
but i am having problem with multiple databases and scripts for each DB,
how can i set flyway to migrate data to all the databases ?
run separate schema for each ?
can i add multiple databases info to the config file?
what should i set my flyway.url to in the properties file
I am assuming you are using the command-line client. It has a -configFile option that lets you choose which config file to use. Simply use one config file per DB and you should be OK.
I am assuming you are using the command-line client. It has a -configFile option that lets you choose which config file to use. Simply use one config file per database and you should be ok.
For example, if you have Flyway installed in a folder called c:/Flyway:
Copy your conf/flyway.conf file to a file called conf/prod.conf.
Open it and update the username, password, and url properties, e.g:
flyway.url=jdbc:postgresql://dbinstance.eu.rds.amazonaws.com:5432/myapp
Then run in a command prompt (shell):
flyway -configFile=c:/flyway/conf/prod.conf migrate

Resources