Quantcast
Viewing all articles
Browse latest Browse all 10

Constraint metadata

There are five types of constraint in SQL Server, and they fall into three categories - programmable constraints, local key constraints and foreign key constraints.

So let's look at the programmable constraints first. These are default constraints, which provide a simple default value for a column, and check constraints, which validate that the data entered for a column passes business rules.

Default constraints are quite simple, and the meta data is available in [sys].[default_constraints]. The columns that this gives us over [sys].[objects] are as follows:

parent_column_idThis is the ID of the column to which the default constraint belongs. You can look up the column using the [parent_object_id] and [parent_column_id] columns to reference [object_id] and [column_id] in [sys].[columns]
definitionThis is the actual definition of the default. Note that the definition listed here will be bracketed and white space will be removed - therefore it's not uncommon to see a default value of 0 defined as ((0)). This is worth bearing in mind - your original SQL defintion of a constraint will not necessarily be re-creatable from meta-data.
is_system_namedThis is 1 if the constraint was system named - i.e. it was not given a name when it was defined. System named constraints are best avoided, as they lead to difficulty in matching up schemas between databases, and documentation of them becomes an onerous task.

So what about check constraints? There's a little more depth to these - the meta data is available in [sys].[check_constraints] and the columns that this gives us over [sys].[objects] are as follows:

is_disabledThis is 1 if the constraint has been disabled using ALTER TABLE ... NOCHECK CONSTRAINT.
is_not_for_replicationThis is 1 if the constraint was created with the NOT FOR REPLICATION keyword. This effectively means that replicated databases do not enforce the constraint during DML operations.
is_not_trustedThis is 1 if the constraint hasn't been verified for all rows. This will be 1 if the constraint has been disabled for some time, or was created on an existing table with the WITH NOCHECK keyword.
parent_column_idThis is much the same as for [parent_column_id] in [sys].[default_constraints] (see above) with the exception that if the value is 0, then the constraint is a check constraint which checks multiple columns, and is therefore a 'table level' check constraint.
definitionThis is the actual definition of the constraint. Note that the same rules apply as for the default constraint definition, and the format of the expression may well be different to the format with which it was created.
uses_database_collationThis is 1 if the database collation makes a difference when evaluating the check constraint. If it does, then the default collation of the database can't be changed.
is_system_namedAs for [sys].[default_constraints], with the same caveats (see above).

So that is the programmable constraints. Pretty straight forward. So what about the two types of key constraint? Well, these are neatly separated in the meta data into the [sys].[key_constraints] and [sys].[foreign_keys] columns.

Let's look at [sys].[key_constraints] first. The additional columns over [sys].[objects] here are:

unique_index_idThis is the ID of the index that enforces the constraint. You can use [parent_object_id] and [unique_index_id] to reference the [object_id] and [index_id] columns in [sys].[indexes]. Note that this is particularly important, because looking at [sys].[indexes], and, in turn, [sys].[index_columns], tells us what columns are involved in the constraint.
is_system_namedAgain, as for [sys].[default_constraints], with the same caveats (see above).

One thing that is uncovered here, through implication, is that functionally there is very little difference between a UNIQUE INDEX, a PRIMARY KEY and a UNIQUE constraint. The only major differences are:

  • A table can have only one PRIMARY KEY
  • A PRIMARY KEY does not accept NULL values

Apart from that, they are, to all intents and purposes, exactly the same. And ignore people who tell you that you can only create a foreign key to a primary key, because that's simply not true.

So, on to the last one, [sys].[foreign_keys]. The additional columns over [sys].[objects] are:

referenced_object_idThis is the ID of the object that the foreign key targets. Note that the ID of the object that is the source of the link is in the [parent_object_id] column.
key_index_idThis is the ID of the index on the referenced object that is targetted by the foreign key. This can be a UNIQUE INDEX, a PRIMARY KEY constraint or a UNIQUE constraint. You can use [referenced_object_id] and [key_index_id] to reference the [object_id] and [index_id] columns in [sys].[indexes].
is_disabledAs for [sys].[check_constraints], this is 1 if the constraint has been disabled using ALTER TABLE ... NOCHECK CONSTRAINT.
is_not_for_replicationAgain, as for [sys].[check_constraints], this is 1 if the constraint was created with the NOT FOR REPLICATION keyword. This effectively means that replicated databases do not enforce the constraint during DML operations.
is_not_trustedThird time lucky, as for [sys].[check_constraints], this is 1 if the constraint hasn't been verified for all rows. This will be 1 if the constraint has been disabled for some time, or was created on an existing table with the WITH NOCHECK keyword.
delete_referential_actionThis is one of the referential actions taken when a parent row is deleted - the referential actions are defined below.
delete_referential_action_descThis is the description of the delete referential action.
update_referential_actionThis is one of the referential actions taken when a parent row is updated - the referential actions are defined below.
update_referential_action_descThis is the description of the update referential action.
is_system_namedThis column, by now, needs no introduction! See above.

The referential actions are:

KeywordValueDescription
NO ACTION0This means that if the delete or update operation would leave orphaned rows in the parent table, then the DML operation fails.
CASCADE1This means that the delete or update is 'cascaded' from the referenced table to the parent table. A delete of a referenced row deletes the parent table rows, an update of a referenced row updates the key values in the parent table row to match.
SET NULL2This means that the delete or update causes rows in the parent table to have their key values set to NULL when rows in the referenced table are updated or deleted.
SET DEFAULT3This means that the delete or update causes rows in the parent table to have their key values set to their default values when rows in the referenced table are updated or deleted.

So - does that tell us everything we need to know about foreign key constraints? No. We still need to find out which columns are involved in the key. Much the same as we could look this up via [sys].[indexes] and [sys].[index_columns] for the key constraints, we need some extra information matching each parent column to each referenced column. Enter [sys].[foreign_key_columns]:

constraint_object_idThis is the ID of the foreign key object itself.
constraint_column_idThis is a slightly misleading column name - I personally feel [key_ordinal] would have been a better choice here. The value is used to order the column reference pairs, and will always be contiguous, starting at 1.
parent_object_idThis is the ID of the parent table - duplicated from [sys].[foreign_keys].
parent_column_idThis is the ID of the column in the parent table - this can be used along with [parent_object_id] to look up the relevant column in [sys].[columns].
referenced_object_idThis is the ID of the referenced table - duplicated from [sys].[foreign_keys].
referenced_column_idThis is the ID of the column in the referenced table - this can be used along with [referenced_object_id] to look up the relevant column in [sys].[columns].

Now we know everything we need to know in order to be able to understand, work with, and re-create constraints from meta data.

Next time we'll take a look at SQL modules, and understand how they tie in with the meta data views.


Viewing all articles
Browse latest Browse all 10

Trending Articles