Im trying to use Keys and Indexson a database and having difficulty. My requirements are as follows:
- I want to be able to have empty string values in the Document No column as well as values
- The constraint should check for Unique Values based on a DatabaseID and DocumentNo ( eg you can have the same document no for 2 different database ID’s)
The table is similar to this (Extra columns removed for simplicity)
RecordID (bigint)
DocumentNo (varchar(12))
DatabaseID (bigint)
So the constraint should not allow inserting or updating a record if there is already a document no for the specified document no and database ID. A blank document no should be allowed to be entered as there are multiple rows with no document no.
Is this possible? if so please could you let me know how.
EDIT:
Here is the Query to Create the View and Constraint:
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW vNoDuplicateDoNos
WITH SCHEMABINDING
AS
SELECT [PODocumentNo],[SageDatabaseID]
FROM dbo.[Order]
WHERE [PODocumentNo] <> ''
GO
--Create an index on the view.
CREATE UNIQUE CLUSTERED INDEX CI_V1_ID
ON vNoDuplicateDoNos ([PODocumentNo],[SageDatabaseID]);
GO
I am not sure about using the GUI for this, but you should use a UNIQUE INDEX with a WHERE condition (assuming you are using SQL Server 2008 or newer):
http://msdn.microsoft.com/en-us/library/ms188783.aspx
Also, I was not able to find an option for the WHERE condition via the GUI in the “Manage Indexes and Keys” dialog.
To be fair, this was suggested by “Martin” in a comment on the Question. I just felt it needed to be explicitly stated with an example.
IF you are using a version of SQL Server prior to 2008 (when Filtered Indexes were added), you can use a Trigger as follows:
The above trigger will look for any existing records that match the two fields but only if the inserted or updated DocumentNo is not empty. If found, it calls ROLLBACK which will cancel the INSERT or UPDATE statement and the RAISERROR will display a message as to what caused the ROLLBACK.
Another option when using a version of SQL Server prior to 2008 is to create an Indexed View on DocumentNo and DatabaseID while filtering out empty DocumentNo records. This was suggested by “Martin” in the comments to this Answer.
Please note that the two SET options as well as the WITH SCHEMABINDING are required for Indexed Views. It is also required that SET ANSI_NULLS ON was used when creating the base table.