Agregar clave única para columnas anulables - SQL Server

I'm using sql server 2008 R2 and would like to apply unique key constraint to nullable columns. This code works good, but if I have multiple columns to add this rule to, it would generate as many 'nullbuster' columns.

ADD nullbuster AS (CASE WHEN column1 IS NULL THEN BranchID ELSE NULL END);
CREATE UNIQUE INDEX UK_Column1 ON tblBranch(column1,nullbuster);

Is there any way that I could achieve the goal without generating new columns.


Followed @marc_s suggestion, here to create an unique key constraint. The target column is BranchCode. Now, there is one record in the table that has NULL for BranchCode. When I try to insert a new record, with Null BranchCode, from c#, it gives an error saying - Cannot insert duplicate key for unique index UK_BranchCode. But, when I manually insert a record in the database, it does accept null values. Where am I going wrong.


Guid gId = Guid.NewGuid();
cmd = new sqlcommand("insert into tblBranch(BranchId,BranchCode) 
cmd.Parameters.AddWithValue("@BranchCode",txtBranchCode.Text);//empty text here

preguntado el 03 de noviembre de 13 a las 07:11

Bueno el texto vacío is NO lo mismo que NULL !! If you want to actually store a NULL, Utilizar DBNull.Value (en lugar de string.Empty) -

I tried cmd.Parameters.AddWithValue("@BranchCode",txtBranchCode.Text.Length > 0 ? txtBranchCode.Text : DBNull.Value.ToString();....It says, Cant insert duplicate key row... -

Sólo tiene que utilizar DBNull.Value - Sin .ToString() ! Maybe you'll need to do the check outside the .AddWithValue() llamada -

Declared a string sName, Outside Addwithvalue. When I say sName=DBNull.Value, it says cannot implicitly convert null to string. When I add , ToString(), it errors out at ExecuteNonQuery :( -

See my updated response - you should NO asignar DBNull.Value to a temporary string, of course - see my code snippet, use that. -

3 Respuestas

So you're creating a nullbuster column for each nullable column you want to index? Seems like overkill....

No seria más fácil to just create índices filtrados for those nullable columns, something like:

CREATE UNIQUE INDEX UK_Column1 ON tblBranch(column1) WHERE column1 IS NOT NULL;

and thus allow any number of NULL entries, while uniquely indexing the other values. That way, you don't need to add all those nullbuster columns just to make indexing possible...

Read more about filtered indexes:

Actualizar: in order to set a parameter to NULL (and not an empty string), use this code:

    cmd.Parameters.AddWithValue("@BranchCode", DBNull.Value);
    cmd.Parameters.AddWithValue("@BranchCode", txtBranchCode.Text);

respondido 04 nov., 13:05

Thank you. If I try to insert values manually in the database table, it accepts multiple null values for that column and also the Unique key constraint works good. But, I'm unable to insert a second null value for the target column through a c# program. It says SQLException. Cannot insert Duplicate values. - Rubí

@Ruby that is not a problem with the index then. Find the bug in your app. - usr

I am unable to find out and updated my question. Someone please help me out - Rubí

THANK YOU MARC. That worked. Could you plz tell me how it would be using objects. The same way didnt work here. tblBranch objBranch = new tblBranch; objBranch.BranchCode = DBNull.value //cant implicity convert.... - Rubí

@Ruby: you can use the DBNull.Value , solamente when you're dealing with ADO.NET stuff - like calling a stored procedure or something like that. Otherwise in your regular .NET code, just use Null en lugar de - marc_s

Use the filtered index suggestion provided by marc_s. You say that you are still getting a unique index violation. What does that tell you? It tells you you are inserting a duplicate key with regards to the index definition. You think, you aren't, but you definitely are.

How to debug that? You look at what you are inserting. You look at gId y txtBranchCode.Text in the debugger. Also, you look at the error message, because it says:

The duplicate key value is ...

All of these clues lead you to find that txtBranchCode.Text is not null, but an empty string. Insert NULL preferiblemente.

respondido 03 nov., 13:16

I suggest you move column1 to a new table and make it unique and non-nullable. Reference the Branch table using a foreign key in the new table. Populate the new table only where you have a (non-null) value for column1.

Creating a new table is the surest way to support any dependencies on column1. A column that permits nulls is not a clave column but column1 apparently should be. Putting that column into a new table also happens to be the only way to satisfy Normal Form and that ought to be the default approach unless you have a very compelling reason to "denormalise" column1 into the Branch table where it doesn't seem to belong.

respondido 03 nov., 13:21

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.