Liquibase check constraint between two tables - liquibase

I want to create two new columns each one of them is in a different table.
For example: on company table i want to create a column with name last_registration_number and the second column called registration_number on employee table with check constraint that follows this logic
registration_number of employee table <= last_registration_number of company table
I couldn't found how to do this between two tables.
What is the proper way to do this?

I suppose Liquibase PRO version could help. It has addCheckConstraint tag (as well as edit and drop). Here's a link to the description.
Also there's a checkConstraint attribute in constraints tag:
<createTable tableName="foo">
<column name="bar" type"integer">
<constraints checkConstraint="your condition here"/>
</column>
</createTable>
but I'm not sure if it'll work, since the pull request basics of implementing checkConstraint is still open.
Or if you can just play around with sql tag which allows you to do anything you want in plain SQL.

Related

Enforce unique constraint across rows in a user defined datatype column

Suppose that you have a database table with only one column of type xml to hold various key/value pairs of user defined datatypes, like this, for example:
Row 1:
<column>
<name>id</name>
<value>1</value>
</column>
<column>
<name>e-mail</name>
<value>abc1#abc.com</value>
</column>
Row 2:
<column>
<name>id</name>
<value>2</value>
</column>
<column>
<name>e-mail</name>
<value>abc2#abc.com</value>
</column>
Now suppose that you want to enforce, in your application code, the integrity constraint that the 'e-mail' column be unique across all the rows, like a database UNIQUE constraint. If I was using a regular database column to hold this, the database itself would take care of this for me, but as I'm using this design now I have to do this by myself.
So, I'm just here asking what would be the right approach to accomplish this in code. In my point of view the only way is to block the entire table everytime a user needs to add another row of update the name 'column' of an existing row.
Any other alternatives?
With a RDBMS (relational) database system it doesn't really make sense to does it? Your value is the xml document itself and if you cared about the email as a value it would have its own column. The fact that it doesn't means you don't care about it being unique - that's the whole point of the relational model.
With postgres you could create a functional index but I'm not sure it's worth the trouble unless this is only a corner of your database and the rest is relational.
There are dozens of document-based database systems that might be suitable for your needs if this is really what you want to do though. It's difficult to say more because they all have different aims and behaviours and track records.

With Liquibase, is there a difference between using a unique <createIndex> and using <column> with a unique constraint?

Liquibase has two ways to define a column as unique:
When creating the table, using <constraints> on the column:
<createTable tableName="my_table">
<column name="my_column">
<constraints unique="true"
uniqueConstraintName="my_table_my_column_uk">
</column>
</createTable>
After creating the table, using <createIndex>:
<createTable tableName="my_table">
<column name="my_column"/>
</createTable>
<createIndex tableName="my_table" unique="true"
indexName="my_table_my_column_uk">
<column name="my_column"/>
</createIndex>
Is there any difference between these two approaches for single-column unique keys?
In my own observations with MySQL, there seems to be no difference. Both declarations (above) yield the same SHOW CREATE TABLE result:
...
UNIQUE_KEY `my_table_my_column_uk` (`my_column`)
...
However, does this hold true for all database implementations, or does <createIndex unique="true"> generate different schema output from <constraint unique="true"/> for different databases?
Background: I have a script that has built the liquibase changelog directly from my relational model in the code. The generation script created BOTH declarations if the model indicated the column was unique. I'm cleaning up the generated results and would like to remove one of the declarations, and want to know if that's appropriate.
See PostgreSQL Documentation:
Note: The preferred way to add a
unique constraint to a table is ALTER
TABLE ... ADD CONSTRAINT. The use of
indexes to enforce unique constraints
could be considered an implementation
detail that should not be accessed
directly. One should, however, be
aware that there's no need to manually
create indexes on unique columns;
doing so would just duplicate the
automatically-created index.
So a unique constraint is a concept which is implemented (in PostgreSQL) with a unique index.
I guess it depends on the target DBMS.
In PostgreSQL, Oracle and DB2 there is a differences between a unique index and an unique constraint.
The unique constraint can be the target of a foreign key constraint but the unique index cannot. Don't know if that is the same with MySQL.

NHibernate HiLo generation and SQL 2005/8 Schemas

I have an issue on my hands that I've spent several days searching for an answer to no avail...
We're using HiLo Id generation, and everything seems to be working fine, as long as the entity table is in the same schema as the hibernate_unique_key table.
The table structure is pretty simple. I have my hi value table in the db as dbo.hibernate_unique_key. Several entity table are also in the dbo schema, and they work without issue. Then we have tables under the "Contact" schema (such as Contact.Person and Contact.Address).
In the Person Mapping file:
<class name="Person" table="Person" schema="Contact">
<id name="Id" unsaved-value="0">
<generator class="hilo">
<param name="max_lo">100</param>
</generator>
</id>
...
When I try to insert a Person entity, I get an error of "Invalid object name 'Contact.hibernate_unique_key'. That error is certainly clear enough. So I add:
<param name="schema">dbo</param>
to my mapping file/generator element. Now, when the SessionFactory is built, I get a "An item with the same key has already been added." error. So now I'm a bit stuck. I can't leave the HiLo generator without a schema, because it picks up the schema from the Class, and I can't specify the schema because it's already been added (presumably because it's my "default_schema" as identified in my XML cfg file).
Am I completely hosed here? Must I either
A) Keep all my tables in the dbo schema or
B) Create a separate HiLo Key table for each unique schema in the DB?
Neither of those scenarios is particularly palatable for my application, so I'm hoping that I can "fix" my mapping files to address this issue.
Only one such table per database should exist. Such data table should imply the following columns (let's call this table Parameters):
HiLoId
TableName
ParamName
HiLoAssigned
In addition to be used as a HiLo assignment data table, this could be used as a parameter table. As such, the ParamName field is required. This could contain data such as:
HiLoId | TableName | ParamName | HiLoAssigned
---------------------------------------------
1 | Parameters| HiLoId | 3
2 | Customers | CustomerId| 9425
3 | Invoices | InvoiceId | 134978
And when you need some other parameters, such as a parameter for a job that would prune your tables for history, then an age parameter for record could be inserted into it.
Well, I'm a little further in the subject than what you actually asked. Just sharing some additional thoughts in database design/architecture.
Take an eye out this question, and see my answer there. This might answer your question as well, and bring further information to this answer.
Have you tried specifying the schema with the table name on all generators (including the ones already in the dbo schema? I.e.
<param name="table">dbo.hibernate_unique_key</param>
The hilo generator looks for a '.' in the table name, and qualifies it (with schema) only if one isn't there.
I don't think there's anything wrong with solution B. Behavior will be pretty much the same.

NHibernate <join> with Multiple Child Records

I have a master record which I'd like to use with. Here's a very basic example mapping example:
<class name="Master">
<join table="Detail">
<key>
<column name="Id" />
</key>
<property name="Name" />
</join>
</class>
This is all very well, and would work but for one problem. The Detail table looks like:
Master_ID EffectiveTo Name
1 1/1/2010 Colin
1 NULL ColinRamsay
There are multiple Detail records for each master, with the current one being the record with a NULL EffectiveTo. With the , I only want that current record to be joined and no other ones.
I'm not sure this is even possible with NH, I know I could create a many-to-one relationship here but I'd also have to create the Detail class and hbm.xml mapping. just seems simpler.
Any suggestions?
join is used to map properties of one class to several tables, when there's a 1-to-1 relationship between the tables.
You can use custom SQL for create, update and delete and load.
Another option is to join onto a view that selects the current records of the Detail table.

How to map many to many association in NHibernate

I have some database tables named Project, Employee and Branch. An employee can work simultaneously on more than one project. Similarly, in a project, there are multiple employees. Also, a project is conducted at a particular branch. To maintain all these relationships, I am using a project_employee_branch table, which will store the related primary keys of the above three tables. As an example, this project_employee_branch table may contain a row like (1,2,3), which means the project whose primary key is 1, is conducted at branch whose primary key is 3, and one of its project member is an employee whose primary key is 2.
How can I map all these associations in NHibernate? I have mapped many-to-one association using foreign key concept, but I don't know how to map these types of associations, where an intermediate table is involved.
First point I'd make is that your database schema and your description don't match, so please take any advice below in the light of that initial caveat. You say that
a project is conducted at a particular branch
which implies there should be a simple foreign key relationship from project to branch. And of course, if this is what the schema looked like, you would have a two-way many-to-many link table and your life would be much easier.
Anyway, with the three-way combination you have, you need to have a collection of components, where the components have many-to-one properties for the other two object types. There is an example in section 7.2 of the NHibernate documentation, but I think it would look something like this in the mapping for Product:
<set name="BranchEmployees" table="product_employee_branch" lazy="true">
<key column="product_id">
<composite-element class="Purchase">
<many-to-one name="Branch" class="Branch" />
<many-to-one name="Employee" class="Employee"/>
</composite-element>
</set>