8 Replies - 1702 Views - Last Post: 10 February 2011 - 03:02 AM

#1 jens  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 430
  • Joined: 09-May 08

Unique constraint that allowes null?

Posted 07 February 2011 - 11:35 PM

Hi!

I would really like to use a constraint on a column that enforces unique entries while still allowing any number of entries with null in that column. I.e. if ((the inserted value is unique) or (the inserted value is null)) then the insertion is accepted else the insertion is not accepted.

Is that possible? How?

Thanks
Jens
Is This A Good Question/Topic? 0
  • +

Replies To: Unique constraint that allowes null?

#2 thava  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 179
  • View blog
  • Posts: 1,598
  • Joined: 17-April 07

Re: Unique constraint that allowes null?

Posted 08 February 2011 - 02:34 AM

yes it is possible

but not straight forward
first you have to create a view for that column with schema binded

then create a unique index for that column
and that's all


/****** Object:  Table [dbo].[test]    Script Date: 02/08/2011 14:54:40 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[test](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[No] [int] NULL,
 CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
ALTER TABLE [dbo].[test]  WITH CHECK ADD  CONSTRAINT [FK_test_test] FOREIGN KEY([Id])
REFERENCES [dbo].[test] ([Id])
GO
ALTER TABLE [dbo].[test] CHECK CONSTRAINT [FK_test_test]
Go

CREATE VIEW  vw_test WITH SCHEMABINDING
AS 
SELECT  t.No FROM dbo.test t WHERE no IS NOT NULL
GO

CREATE UNIQUE CLUSTERED INDEX idxuno ON vw_test(no)
GO

INSERT INTO test  (No)VALUES( 1 )
GO
SELECT * FROM test 
GO
INSERT INTO test  (No)VALUES( NULL )
GO
INSERT INTO test  (No)VALUES( NULL )
GO
SELECT * FROM test 
GO
INSERT INTO test  (No)VALUES( 1 )
--- not this line will generate a error
GO


just run this query in your master database

happy codng :^: :^: :^: :^: :^:

This post has been edited by thava: 08 February 2011 - 02:38 AM

Was This Post Helpful? 1
  • +
  • -

#3 jens  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 430
  • Joined: 09-May 08

Re: Unique constraint that allowes null?

Posted 08 February 2011 - 02:51 AM

Hi, thanks for the reply!

I found another solution which does not require a view here.

CREATE TABLE dupNulls (
pk int identity(1,1) primary key,
X  int NULL,
nullbuster as (case when X is null then pk else 0 end),
CONSTRAINT dupNulls_uqX UNIQUE (X,nullbuster)
)

INSERT INTO dupNulls(X) VALUES (1)
INSERT INTO dupNulls(X) VALUES (NULL)
INSERT INTO dupNulls(X) VALUES (NULL)
GO
SELECT pk, X, nullbuster FROM dupNulls
UPDATE dupNulls SET X = 1 WHERE pk = 2
GO
SELECT pk, X, nullbuster FROM dupNulls
UPDATE dupNulls SET X = 2 WHERE pk = 2
SELECT pk, X, nullbuster FROM dupNulls
DROP TABLE dupNulls



Regards
Jens
Was This Post Helpful? 1
  • +
  • -

#4 baavgai  Icon User is online

  • Dreaming Coder
  • member icon

Reputation: 5641
  • View blog
  • Posts: 12,358
  • Joined: 16-October 07

Re: Unique constraint that allowes null?

Posted 08 February 2011 - 05:10 AM

Thats clever; thanks.

Note, the NULL in MS SQL is a major failing. It makes me twitch every time I have to deal with it.

Codd ( father of relational database theory ) defines a null value as:

Quote

Rule 3: Systematic treatment of null values:
The DBMS must allow each field to remain null (or empty). Specifically, it must support a representation of "missing information and inapplicable information" that is systematic, distinct from all regular values (for example, "distinct from zero or any other number", in the case of numeric values), and independent of data type. It is also implied that such representations must be manipulated by the DBMS in a systematic way.
-- http://en.wikipedia.org/wiki/Codd's_12_rules


Oracle, the first implemented version of SQL, interpreted this rule as "A null can be assigned but it cannot be equated with anything: even itself." As a result, in an Oracle database ( and several others ), you can have a unique constraint and as many nulls as you like. Null isn't equal to null; it isn't equal to anything.

It's a challenging concept for many. Including, apparently, Microsoft.

Edit: Almost forgot about this! I think I had a problem with it once, but for completeness. MS does offer a way to be ANSI compliant. SET ANSI_NULLS

This post has been edited by baavgai: 08 February 2011 - 05:15 AM

Was This Post Helpful? 1
  • +
  • -

#5 jens  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 430
  • Joined: 09-May 08

Re: Unique constraint that allowes null?

Posted 08 February 2011 - 02:13 PM

View Postbaavgai, on 08 February 2011 - 01:10 PM, said:

Edit: Almost forgot about this! I think I had a problem with it once, but for completeness. MS does offer a way to be ANSI compliant. SET ANSI_NULLS


Thank you. That was interesting. After a quick read of the page I'm a little confused however. I do understand what you quoted on the NULL != NULL and as a consequence one will not be able to "SELECT .... WHERE xxx <> NULL" but how does one get only rows that have xxx not null or rows that have xxx set to null in that case?

Regards
Jens
Was This Post Helpful? 0
  • +
  • -

#6 baavgai  Icon User is online

  • Dreaming Coder
  • member icon

Reputation: 5641
  • View blog
  • Posts: 12,358
  • Joined: 16-October 07

Re: Unique constraint that allowes null?

Posted 08 February 2011 - 02:16 PM

You just said it. "Where Field!=NULL" is not the same as "Where Field NOT NULL". That's part of the reason for the syntax. It's a boolean statement, not an equality.
Was This Post Helpful? 1
  • +
  • -

#7 thava  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 179
  • View blog
  • Posts: 1,598
  • Joined: 17-April 07

Re: Unique constraint that allowes null?

Posted 09 February 2011 - 01:59 AM

View Postjens, on 08 February 2011 - 02:51 AM, said:

Hi, thanks for the reply!

I found another solution which does not require a view here.

CREATE TABLE dupNulls (
pk int identity(1,1) primary key,
X  int NULL,
nullbuster as (case when X is null then pk else 0 end),
CONSTRAINT dupNulls_uqX UNIQUE (X,nullbuster)
)

INSERT INTO dupNulls(X) VALUES (1)
INSERT INTO dupNulls(X) VALUES (NULL)
INSERT INTO dupNulls(X) VALUES (NULL)
GO
SELECT pk, X, nullbuster FROM dupNulls
UPDATE dupNulls SET X = 1 WHERE pk = 2
GO
SELECT pk, X, nullbuster FROM dupNulls
UPDATE dupNulls SET X = 2 WHERE pk = 2
SELECT pk, X, nullbuster FROM dupNulls
DROP TABLE dupNulls



Regards
Jens


a computed column and a unique constraint that's great,
now what happen when there is a combination of primary keys
i think this logic will not work
Was This Post Helpful? 0
  • +
  • -

#8 baavgai  Icon User is online

  • Dreaming Coder
  • member icon

Reputation: 5641
  • View blog
  • Posts: 12,358
  • Joined: 16-October 07

Re: Unique constraint that allowes null?

Posted 09 February 2011 - 06:31 AM

Interesting observation. Regardless of PK, you could do it:
CREATE TABLE #dupNulls (
	FirstName nvarchar(30) not null,
	LastName nvarchar(60) not null,
	IdNum int,
	nullbuster as (case when IdNum is null then FirstName+LastName else '~' end),
	CONSTRAINT dupNulls_uqIdNum UNIQUE (IdNum,nullbuster),
	CONSTRAINT PkdupNulls primary key (FirstName,LastName)
)



However, if you have a compound PK then you aren't using identity, so we can still use it:
CREATE TABLE #dupNulls (
	FirstName nvarchar(30) not null,
	LastName nvarchar(60) not null,
	IdNum int,
	NotNullKey int identity,
	nullbuster as (case when IdNum is null then NotNullKey else 0 end),
	CONSTRAINT dupNulls_uqIdNum UNIQUE (IdNum,nullbuster),
	CONSTRAINT PkdupNulls primary key (FirstName,LastName)
)


Was This Post Helpful? 2
  • +
  • -

#9 thava  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 179
  • View blog
  • Posts: 1,598
  • Joined: 17-April 07

Re: Unique constraint that allowes null?

Posted 10 February 2011 - 03:02 AM

fine and enough
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1