We use Alembic for our Database version control for Snowflake. Alembic is a "migration" tool where you can run multiple changes (or a migration) to your Data Warehouse. It's essentially an add-on to the SQLAlchemy library in Python.
When developing locally, we create a clone of our database, and test our migration changes to the cloned database. Once we know it works, we push it to GitLab, get it approved, then we can run a CI/CD pipeline that has accountadmin
credentials to make the change in production.
Since it's written in Python, you can connect this to your Git tool (like GitHub or GitLab) and submit changes in a Merge Request and get approval before running this in your Production database.
Here's the documentation: https://alembic.sqlalchemy.org/en/latest/
This is also officially supported according to Snowflake documentation: https://docs.snowflake.net/manuals/user-guide/sqlalchemy.html#alembic-support
An example Alembic migration might look like:
Revision ID: 78a3acc7fbb2
Revises: 3f2ee8d809a6
Create Date: 2019-11-06 11:40:38.438468
"""
# revision identifiers, used by Alembic.
revision = '78a3acc7fbb2'
down_revision = '3f2ee8d809a6'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
op.create_table('test_table',
sa.Column('op', sa.String(length=255), nullable=True),
sa.Column('id', sa.String(length=255), nullable=False),
sa.Column('amount', sa.BigInteger(), nullable=True),
sa.Column('reason', sa.String(length=255), nullable=True),
sa.Column('deleted', sa.Boolean(), nullable=True),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('company_id', sa.Integer(), nullable=True),
sa.Column('inserted_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('dw_import_filename', sa.String(length=255), nullable=True),
sa.Column('dw_import_file_row_number', sa.Integer(), nullable=True),
sa.Column('dw_import_timestamp', sa.TIMESTAMP(), nullable=True),
sa.PrimaryKeyConstraint('id'),
schema='test_schema'
)
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('test_table', schema='test_schema')
As you can see, you have to supply an upgrade and have the ability to downgrade, which reverses the upgrade. If you have any other questions about Alembic or if this interests you then I'd be happy to explain more.