Skip to main content

Command Palette

Search for a command to run...

Part 5: SQLcl Project (It will forever change your Database & APEX deployments)

Updated
7 min read
Part 5: SQLcl Project (It will forever change your Database & APEX deployments)
R

Oracle APEX & PL/SQL Developer with 10 years of experience in IT, including financial systems for government administration, energy, banking and logistics industry. Enthusiast of database automation. Oracle ACE Associate. Certified Liquibase database versioning tool fan. Speaker at Kscope, APEX World, SOUG, HrOUG, POUG and DOAG. Likes swimming in icy cold lakes in winter and playing basketball.

Welcome to part 5 of "A whirlwind tour of Database Schema Changes Tracking Tools"

In this article, I will provide a general overview and test the basic functionalities of the Oracle SQLcl “Project” command.

I will cover only CI/CD for database changes. The APEX part is covered in a separate blog post here. However, I encourage you to read a current article first.

If you’re interested in more details, read the official documentation here.

Prerequisites

  • I have two environments (DEV and PROD) on my Docker for MacOS (read here how I’ve set it).

  • I will use connection names DOCKER_HR_DEV and DOCKER_HR_PROD to connect to it. (read about connection aliases here)

  • DEV and PROD databases have the same number of objects created manually in past deployments.

  • All commands you will see in this blog will be executed using SQLcl 24.3.1 (read how to install it here)

1.Start using SQLcl Project with existing or new databases using project init

  1. Create a SQLcl database project

  • I have an empty folder SQLCL_PROJECT in my VS Code.
  • Now, I will connect to my HR schema on DEV.
sql -name DOCKER_HR_DEV
  • Initialize new project with project init command.

  • My project will be called “BOMBSHELL”, and I want to initialize it with the schema “HR”.

--DOCKER_HR_DEV
project init -name BOMBSHELL -schemas HR
  • Folders and files visible below were auto-created by SQLcl.
  1. Initialize GIT repository.

  • Now, I have to initialize a new GIT repository for created files and commit it.
!git init --initial-branch=main
!git add .
!git commit -m "chore: initializing repository with default project BOMBSHELL files"
  1. Create the base-release branch, export DB objects from DEV and commit.

  • Now, I will create a branch “base-release”, connect to DOCKER_HR_DEV, and export database objects into files.

  • The steps are the same for new projects. You will export your files once some objects are created in the database.

    # this command creates new branch and switches to it
    # or use GUI tool to create it
    !git checkout -b base-release
    
  • Now, I’ll export all DB files from DEV.
--DOCKER_HR_DEV
project export
  • My database objects were exported into SQL files - see examples below.
  • I have committed my base-release into GIT

  1. Use project stage to create a deployment script

--DOCKER_HR_DEV
project stage
  • Files necessary for deployment were automatically created:
  1. Verify project using project verify

project verify -verbose

All good to go.

  1. Run project release to finish release 1.0

  • I will call my base release version “1.0”.
--DOCKER_HR_DEV
project release -version 1.0 -verbose
  • SQLcl terminal says clearly what happened:
  • My release was moved to /releases/1.0, and my next release is empty
  1. Generate an artifact representing the current stage of the project using gen artifact

--DOCKER_HR_DEV
project gen-artifact -version 1.0-base-release
  1. Deploy release (version 1.0) to PROD using project deploy

For new project

  • If it were a new project, I would’ve deployed all my code to PROD using project deploy command

  • It would look like that (connected to PROD or any other environments)

--DOCKER_HR_PROD
project deploy -file artifact/BOMBSHELL-1.0-base-release.zip -verbose

For existing projects

  • In my case (I already have objects in PROD), I have to manually mark version 1.0 as released to PROD by running liquibase changelog-sync command

  • This command won’t change any of your DB objects - it will only create necessary liquibase tables and make some inserts into databasechangelog table

--DOCKER_HR_PROD
sql -name DOCKER_HR_PROD
liquibase changelog-sync -chf dist/releases/main.changelog.xml
  1. GIT Merge “base-release”(DEV) branch into “main” (PROD)

  • I have to merge my base-release branch into main because, at this moment,t my DEV (base-release) is equal to PROD(main)

2. Create new changes on DEV and deploy to PROD as version 1.1

  1. Make some changes directly in DEV environment (use VS Code or SQL Dev etc.)

INSERT INTO HR.COUNTRIES (COUNTRY_ID, COUNTRY_NAME, REGION_ID) VALUES ('PL', 'Poland', '10');

CREATE TABLE HR.PARAMETERS (NAME VARCHAR2(50),
                           VALUE VARCHAR2(50));

ALTER TABLE HR.EMPLOYEES 
ADD (ADDRESS VARCHAR2(100) );

 CREATE OR REPLACE PROCEDURE HR.SECURE_DML
 IS
 BEGIN
    IF TO_CHAR(SYSDATE, 'HH24:MI') not between '08:00' and '18:00'
       or TO_CHAR(SYSDATE, 'DY') in ('SAT', 'SUN')
    THEN
       RAISE_APPLICATION_ERROR(-20205,
                               'You may only make changes during normal office hours (this bracket is a change)');
    END IF;
END SECURE_DML;
/

INSERT INTO HR.PARAMETERS (name, value) VALUES ('MY_BLOG_URL','rafal.hashnode.dev');
COMMIT;
  1. Create a new GIT branch called version-1.1

  2. Export changes made using project export

--on branch version-1.1
--connected to DOCKER_HR_DEV
project export
  • This command exported my actual state of DEV database objects. As we can see, there are three new/changed files:
  1. Use project stage to create a deployment script

--DOCKER_HR_DEV
project stage
  • This command created some new files for my release 1.1
  • As you can notice, SQLcl automatically prepared required scripts
  1. Use project stage add-custom to deploy custom scripts, e.g DML

  • As you may remember, on my DEV, in addition to changes in the EMPLOYEES and PARAMETERS tables and the procedure SECURE_DML, I’ve also executed two inserts into the COUNTRIES and PARAMETERS tables.

  • This is something that SQLcl won’t track automatically, and we need to use add-custom command for that

  • That’s why I’ve created two files for DMLs in both tables:

--DOCKER_HR_DEV
project stage add-custom -file-name dml_employees
project stage add-custom -file-name dml_countries
  • And SQLcl automatically created those files:
  • There’s no need to change anything in these files. I will only put my insert scripts there:
  1. Verify project using project verify

  • I will verify my project again:
--DOCKER_HR_DEV
project verify
  • And we are good to go
  1. Run project release to finish release 1.1

--DOCKER_HR_DEV
project release -version 1.1 -verbose
  • SQLcl terminal says clearly what happened:
  • My release was moved to /releases/1.1, and my next release is empty
  1. GIT Commit version 1.1 and merge into the main branch

  • I like to do this to make it clear. Since my release is ready to deploy to PROD, I should deploy it from the main (PROD) branch.

  • Git commit version 1.1 on branch version 1.1

  • Merge branch version-1.1 into MAIN

  1. Generate an artifact representing the current stage (version-1.1) of the project using gen artifact

  • Now, I will create an artifact for my version-1.1
--DOCKER_HR_PROD
--on GIT branch MAIN(prod)
project gen-artifact -version version-1.1
  1. Deploy release (version-1.1) to PROD using project deploy

  • I’m ready to deploy my changes to PROD.
--DOCKER_HR_PROD
project deploy -file artifact/BOMBSHELL-version-1.1.zip -verbose
  • The SQLcl terminal clearly states what happened, but the most important thing is that all my five changes were deployed to PROD.

I hope you like this article.

Drop me a comment if you have any questions or thoughts.

Bests,

Rafal

PS SQLcl Projects also supports APEX deployment, which I will cover in a separate article.

PPS: Wondering about the picture? It’s right before the sunrise in Kielce (Poland)

Other tested Tools

Tool review & test Official documentation
Liquibase (standalone Open-Source edition) Link Doc
Oracle SQLcl with Liquibase Link Doc
Flyway Community Edition Link Doc
D.O.M.E - Deployment Organisation Made Easy Link Doc, Videos
Oracle’s SQLcl “Project” feature Link Doc
ADT - APEX Deployment Tool Not published yet Doc
dbFlow Not published yet Doc
L

Hi How do you manage versions in multi developer environment? So two or more people working in different branches on different features?

R

I recommend watching this office hours video: https://www.youtube.com/watch?v=EM3_2Dd3LOs.Guys from Oracle show examples of when 2 developers are working on different tickets in the same environment.

L

Rafal Grzegorczyk Thank you, I did have a watch. One thing I'm still unsure is that on demo they working on main which often is protected so running project release is hard. However running that in branch does not allow multiple developers working together as each branch would essentially cut its own release and hence my question about managing this. Or did I misunderstood the process and missing something? Thanks in advance.

R

Lukasz Wasylow If you will "project export", then indeed, you will export everything. So a solution would be e.g.:

  1. Developer 1 is working on some changes in the database, and periodically, he exports only his changes to a branch, let's say branch "feature1."
  2. Developer2 is working on his changes on the "feature2" branch and exports his changes.

"project export -o OBJECT_NAME"

At the end, their changes are merged:

  • feature1 into e.g. branch "version_2.0"
  • feature1 into branch "version_2.0"

Then, the privileged user lets call him Release Guy execute the "project stage" command, then "project release" etc.

Does it answer your question? :)

1
L

Rafal Grzegorczyk It does, yes thank you :) Indeed it seem doable with a sort of git flow approach. Trunk based seems more complex. But I will try it out, looking for alternatives for flyway and this looked promising. Again thank you for the help and your time, much appreciated 🙏

P
Peter1y ago

Is it possible to add some custom text to the exports? I would like to add liquibase formatted sql to the object exports as well, just like add-custom.

R

Hi Peter. SQLcl Projects use Liquibase in the background so there shouldn't be any problems if you will just manually add new changesets / changelogs -> sth like here https://rafal.hashnode.dev/liquibase-tutorial-a-step-by-step-guide-for-you#:~:text=anddepartmentstables).*-,Changesets,-Database%20change%20is

P
Peter1y ago

Rafal Grzegorczyk I mean, I would like liquibase formatted sql in the output from the command "project export" that export db objects.

R

Peter Files, that are created with "project export" are already "Liquibase formatted sql". But if you want to somehow modify them before it's exported then I would recommend deep diving into Oracle Docs - there are some config options

H

Hey Peter, Not sure if I understand your use-case. But overall after you exported your objects using project export, you can then call project stage and you will find your objects wrapped with liquibase metadata under the dist folder.

More from this blog

Keep It Simple. Developer's tips.

53 posts