So I have an Oracle database which I am updating in liquibase... in the process of testing my DB build system, I created a new change which is identical in content to an older change with a different ID. Both are adding a column with the same name, using SQL. I would expect the 2nd to fail, since it would attempt to create a column which already exists, but the liquibase command updateTestingRollback reports:
Liquibase 'updateTestingRollback' Successful
Any ideas what the potential cause may be?
<changeSet id="2" author="anonymous" failOnError="true">
<sql>ALTER TABLE person ADD (col_a VARCHAR(1));</sql>
<rollback>ALTER TABLE person DROP COLUMN col_a;</rollback>
</changeSet>
<changeSet id="3" author="anonymous" failOnError="true">
<sql>ALTER TABLE person ADD (col_a VARCHAR(1));</sql>
<rollback>ALTER TABLE person DROP COLUMN col_a;</rollback>
</changeSet>
You might try running with the --logLevel=debug flag added to make sure, but my guess is that oracle is not returning an error code when the sql for the second change is applied. if you use the <sql> tag rather than more specific change type tags (i.e. the <addColumn> tag), liquibase has a more difficult time detecting problems.
Related
What’s the most efficient way to insert data with a proper order? For example I have 2 tables:
create table Primary (dataset_id number, info varchar2(100) PRIMARY KEY dataset_id);
create table Foreign (dataset_id number, category varchar2(100) FOREIGN KEY dataset_id REFERENCES Primary(dataset_id))
Now I run liquibase data to generate data.xml for the insertion. However, when I deployed to the Oracle DB, I found the foreign key issue. Liquibase exported data.xml in the alphabetical order of tables so the data in Primary is executed after Foreign (since P is behind F).
Each time I have to manully copy and paste the data for Foreign below the Primary… Is there any efficient way to insert the data with the dependency order? In other words, alway insert Primary table at first.
I found some solutions from the Internet but all of them are out of date. Was it added as a new feature so that we can achieve via command directly? I don’t want to touch data.xml once it’s auto-exported. Thanks!
It is always necessary to inspect the XML changesets Liquibase generates. As you mention, Liquibase may end up generating changesets in the incorrect order and you will need to update generated changesets and reorder them so that they can be deployed in the correct order.
Why not export to different XML changelogs such that data for Primary tables goes into primary.xml and data for Foreign table goes into foreign.xml. Then you can use a master changelog to instruct Liquibase the order in which to deploy, e.g.,
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.3.xsd">
<include file="primary.xml"/>
<include file="foreign.xml"/>
</databaseChangeLog>
I want to create and alter DB user using Liquibase. Following are the SQL queries to do so for Oracle DB.
change password:
ALTER USER ADMIN IDENTIFIED BY ${user.password};
create user:
CREATE USER appuser IDENTIFIED BY ${user.password};
I want to make the password parameterized, but changelog Property Substitution is not available in SQL format.
I am choosing XML as the fallback option, but not able to convert above queries into Liquibase XML format. I need help in converting alter/create user queries into XML.
You can use the SQL tag inside XML changeset and write any SQL query withing the tag as follows:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<changeSet author="authorName" id="some-unique-id" dbms="${dbType}">
<sql endDelimiter=";" splitStatements="true" stripComments="true">
**My SQL query/ transactional logic goes here**
CREATE USER appuser IDENTIFIED BY ${user.password};
</sql>
</changeSet>
</databaseChangeLog>
and then you can use Liquibase changelog property substitution with the password value. Using SQL tag will allow you to execute any SQL query (ofcourse in proper syntax) without you having to worry about the XML syntax for liquibase changeset.
For more details on property substitution, have a look at my answer on this post
This is regarding Liquibase insert records. Suppose in version v1 I have an xml file with 50 insert records and I want to add 30 more insert records in version 2. Can I go with same file and change id and add these records? Actually, I did in same file and I got a "unique constraints error" while updating commands.
at liquibase.database.AbstractJdbcDatabase.executeStatements(AbstractJdbcDatabase.java:1211)
at liquibase.changelog.ChangeSet.execute(ChangeSet.java:600)
... 7 common frames omitted
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value
violates unique constraint
No, the idea is that you would want to have two changesets. You already have a changeset in v1 that adds the first 50. You should add a second changeset to add the next 30. Changesets (for the most part) should be considered immutable once they have been deployed anywhere besides your own local developer database. The main exception to that is changesets that deploy things like functions or procedures, where the SQL code in the file is always the latest and most correct version.
I am running the following changeset on an Oracle 12 database (the latest official docker image). When the changeset is executed, I get a SQL error:
Error: ORA-01735: invalid ALTER TABLE option
[Failed SQL: ALTER TABLE TEST.LANGUAGE ADD CONSTRAINT SYS_C0010528 PRIMARY KEY (ID) USING INDEX TEST.SYS_C0010528]
I generated the changeset from an existing Oracle database schema using Liquibase tools, with minor alterations.
Does liquibase not support Oracle 12?
How do I configure liquibase to generate Oracle 12-compatible SQL?
Is this a settings issue, or a bug in Liquibase?
Details:
It looks like Oracle doesn't accept the qualifier for the index name in the USING INDEX statement. The following revised SQL seems to work as intended:
ALTER TABLE TEST.LANGUAGE ADD CONSTRAINT SYS_C0010528 PRIMARY KEY (ID) USING INDEX SYS_C0010528
Here is the changeset definition:
<changeSet author="rmorrise (generated)" id="1507039841670-7">
<preConditions onFail="MARK_RAN">
<not>
<primaryKeyExists tableName="LANGUAGE"/>
</not>
</preConditions>
<createIndex indexName="SYS_C0010528" tableName="LANGUAGE" unique="true">
<column name="ID"/>
</createIndex>
<addPrimaryKey columnNames="ID" constraintName="SYS_C0010528" forIndexName="SYS_C0010528" tableName="LANGUAGE"/>
</changeSet>
Update:
I fixed the <addPrimaryKey> entries by replacing them with <sql> tags, but I got the same error on <addUniqueConstraint> with forIndexName.
Here is the generated SQL to create the index. It appears to be created in the same schema.
CREATE UNIQUE INDEX TEST.UK46FCA532E38E4F92860631AA28CB ON TEST.MESSAGE_ROLE(TEMPLATE_ID, LABEL);
ALTER TABLE TEST.MESSAGE_ROLE ADD CONSTRAINT UK46FCA532E38E4F92860631AA28CB UNIQUE (TEMPLATE_ID, LABEL) USING INDEX TEST.UK46FCA532E38E4F92860631AA28CB;
To answer Alex's question about the use of system object names: The schema was originally generated by hbm2ddl and migrated to liquibase using generateChangelog.
A query to dba_objects confirms that the OWNER is TEST.
I had a similar problem and as I was reading this topic I see that we both named our schema "TEST".
I changed the schema's name and it worked immediatly.
I want to generate a changelog XML from an existing Oracle schema, let's name it A. This schema contains references to another schema, schema B. Tables in schema A for example contain foreign keys referencing tables in schema B. User A has only SELECT and REFERENCES privileges on the tables of schema B.
When I try to create a database changelog for schema A, tables and constraints from B are included, even though they are not owned by user A. Is there any way to change this behavior? I tries to set the defaultCatalogName, defaultSchemaName, changelogCatalogName and changelogSchemaName parameters, but nothing changed.
It should work the way you expect, but due to bug https://liquibase.jira.com/browse/CORE-1784 it is not working as expected. It is fixed for the upcoming 3.2.0 release, probably out in mid March.