I have been working with a client on a complex integration into Dynamics GP and have come across a few instances where peoples’ understanding of Create Table Default and Constraint Default is, well… not very understood.
So, I thought perhaps it is time to share some of my Create Table Default vs Constraint Default wisdom.
SQL Table Default
As a reminder, to create a basic table in SQL you use the common syntax:
CREATE TABLE
{ database_name.schema_name.table_name | schema_name.table_name | table_name }
( { <column_definition> } [ ,... n ] )
[ ; ]
Example:
CREATE TABLE [dbo].[Customer] (
[IDNumber] bigint NOT NULL IDENTITY(1,1),
[Name] varchar(50) NOT NULL,
[Address] varchar(50) NOT NULL,
[City] varchar(30) NOT NULL,
[Postal] varchar(10) NOT NULL
) ON [Primary];
The first column is the field name, the second column is the data type, and the third column is NOT NULL – meaning it cannot be a NULL value. All Dynamics GP Tables are built like this.
The IDENTITY (1,1) on the field [IDNumber] indicates that this is the IDENTITY column, which automatically generates a unique value for the field [IDNumber] when a new record is inserted into the table. This IDENTITY field also acts as a primary key on the table, meaning, the value can only exist once in the table.
The syntax is IDENTITY( <seed>, <increment> ).
<seed> is the originating number, or the first record that is created.
<increment> is the amount you have identified to add for each new entry, from the previous entry.
Another available feature when we create SQL tables, is to add a “Default” value in a field of a new record, which will automatically populate the field if NO value is populated for that field on INSERT.
This is the DEFAULT value as in the example below:
CREATE TABLE [dbo].[Invoice] (
[TrxNumber] bigint NOT NULL IDENTITY(1,1),
[Amount] numeric(19,5) NOT NULL,
[Date] datetime NOT NULL DEFAULT GETUTCDATE(),
[User] varchar(30) NOT NULL DEFAULT USER_NAME()
) ON [Primary];
The [Date] and [User] fields have a DEFAULT defined for the example created above.
When you create a new record, if the values for a field that have a DEFAULT defined on the field of the table, are NOT passed with the INSERT statement, then the table will add those DEFAULT values for you automatically and no insert error will occur.
In the example above, we are adding the current date and time in UTC format for the field [Date] and the SQL user’s name for the field [User].
This DEFAULT syntax is adding to the table a “system assigned name” constraint to the table.
Before we progress into the Constraint conversation, let’s talk about the DEFAULT property and why this can be a SQL developer’s best friend.
Using the example above, when we create stored procedures or a simple insert statement, we no longer need to include those fields that have DEFAULT values assigned. Consider this code:
INSERT INTO [dbo].[Invoice] ( [Amount] )
VALUES ( 25.00 )
This is all the code required in the example above. Why, you may ask?
The field [TrxNumber] is an IDENTITY field, thus it will auto generate the next number.
The field [Date] has a DEFAULT constraint to fill in the current UTC date / time and the field [User] has a DEFAULT constraint to fill in the field with the current SQL user’s name (identity).
Constraint Default
When I run the code above and check on the constraint names this is what I receive:
EXECUTE sp_helpconstraint [dbo.Invoice];

Now, let’s DROP the table [dbo].[Invoice], and re-create the table and check the constraint names again.
DROP TABLE IF EXISTS [dbo].[Invoice];

You will notice that the constraint names change.
So why is this a potential concern?
The constraint will not be uniform (same name) in all environments for the same tables.
Think of it this way…
You are in a multi-tenant environment or in a multi DBF environment like Development, Testing and Production that all have the same tables. You are NOT able to alter or disable the DEFAULT constraint for all tables in all environments with a simple T-SQL script.
Not to say you could not develop a more complex T-SQL script with a cursor or OVER WITH function. But why not just make your life simpler?
The best practice code example is Example 1:
CREATE TABLE [dbo].[Invoice] (
[TrxNumber] bigint NOT NULL IDENTITY(1,1),
[Amount] numeric(19,5) NOT NULL,
[Date] datetime NOT NULL,
[User] varchar(30) NOT NULL
) ON [Primary];
ALTER TABLE [dbo].[Invoice]
ADD CONSTRAINT [DF_Invoice_Date] DEFAULT (GETUTCDATE() ) FOR [Date];
ALTER TABLE [dbo].[Invoice]
ADD CONSTRAINT [DF_Invoice_User] DEFAULT (USER_NAME() ) FOR [User];
Example #2:
CREATE TABLE [dbo].[Invoice] (
[TrxNumber] bigint NOT NULL IDENTITY(1,1),
[Amount] numeric(19,5) NOT NULL,
[Date] datetime NOT NULL CONSTRAINT [DF_Invoice_Date] DEFAULT GETUTCDATE(),
[User] varchar(30) NOT NULL CONSTRAINT [DF_Invoice_User] DEFAULT USER_NAME()
) ON [Primary];
So what is the difference between Example 1 and Example 2?
Example 1 follows the DML specification (Data Manipulation Language) and will work in any SQL database system. However, Example 2 will NOT work in other DBF systems. Both examples are correct coding for Microsoft T-SQL.
I always try and stay with DML standards, so my code snippets can be ported to other systems. I hope this is useful to you SQL people out there.
The post SQL Table Default Vs. Constraint Default appeared first on Dynamics Communities.