tags:

views:

890

answers:

7

I've seen a few web searches and responses to this but it seems they all involve views.

How can I adjust a column so that it only allows NULL or a unique value?

In my case there's a table with stock items in which only the server items have a serial number. The rest are null. I would like to enforce some kind of control against entering the same serials.

Also, I cannot redesign the architecture as I'm writing a new front end to a still live site.

A: 

Can you validate from the frontend? Before you insert or commit your data make sure it is unique or NULL.

northpole
I'm doing this to keep it clean it's the most simple solution
Jan W.
+6  A: 

In MySQL, a UNIQUE column that's also nullable allows any number of nulls (in all engines). So, if you're using MySQL, just add a UNIQUE constraint to the column of interest. This behavior is the SQL standard and is also supported by PostgreSQL and SQLite (and apparently Oracle for single-column UNIQUE constraint only, though I can't confirm this).

However, this SQL standard behavior won't necessarily work for all other RDBMS engines, such as SQL Server or DB2; if you specify what engines you need to support, we may be able to offer more specific suggestions.

Alex Martelli
PostgreSQL also supports this behavior.
Michael E
Right, and SQLite and Oracle, too, as I said in the first paragraph of the answer -- it _is_ the SQL standard behavior, after all, though there are always "black sheep";-).
Alex Martelli
+4  A: 

SQL Server allows creating UNIQUE indexes that accept NULL values, though it takes a little trick.

Create a view that selects only non-NULL columns and create the UNIQUE INDEX on the view:

CREATE VIEW myview
AS
SELECT  *
FROM    mytable
WHERE   mycolumn IS NOT NULL

CREATE UNIQUE INDEX ux_myview_mycolumn ON myview (mycolumn)

Note that you'll need to perform INSERT's and UPDATE's on the view instead of table.

You may do it with an INSTEAD OF trigger:

CREATE TRIGGER trg_mytable_insert ON mytable
INSTEAD OF INSERT
AS
BEGIN
        INSERT
        INTO    myview
        SELECT  *
        FROM    inserted
END
Quassnoi
don't have a 2k5 server to hand, but a quick test on 2k with an integer column with a unique index on it and allow nulls prevent you from adding a second <null> value. e.g. 1,2,<NULL>,4,5 == GOOD / 1,2,<NULL>,4,5,<NULL> == NOT ALLOWED
Eoin Campbell
Not with multiple NULLs. SQL Server does not comply with the ANSI SQL (introduced after SQLServer's implementation) on this: https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=299229
Cade Roux
Sure, sure :) But I remember this is possible somehow!
Quassnoi
A: 

You could do it with a Trigger instead...

Index the column but without a unique constraint Allow nulls Stick a trigger on the table that on INSERT and UPDATE you check if the column value your attempting to insert is either NULL or doesn't already exist in the table

Eoin Campbell
A: 

I don't know what database you're using, but in Postgres, you can define a "before insert or update" trigger that can return a special value to reject the insert. You could use it to enforce a constraint like this on your table if there isn't a native way to do it.

Brian L
A: 

What platform is this for?

For SQL Server see this blog post which shows a technique using indexed views.

Cade Roux
+2  A: 

If you're using MS SQL Server 2008, then you can use a filtered unique index to achieve this. Have a look at this forum thread for details.

Matt
Here's also an article that includes the WHERE portion:http://improvingsoftware.com/2010/03/26/creating-a-unique-constraint-that-ignores-nulls-in-sql-server/
MattB