Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Constraint error when inserting

Author  Topic 

R
Constraint Violating Yak Guru

328 Posts

Posted - 2009-08-17 : 10:55:34
Hi all

I keep getting an error when I run an INSERT command against a table. The error is as follows:


The INSERT statement conflicted with the CHECK constraint "CK_tbl_UserTargetLevels". The conflict occurred in database "myDB", table "dbo.tbl_UserTargetLevels".
[code]

I can't see what's causing this, although it must be something really simple because I've been staring at it far too long. Please can anyone spot the problem with the insert? Here's the full code:

[code]
CREATE TABLE tbl_UserTargetLevels
(
[ID] INT IDENTITY(1,1) PRIMARY KEY,
userID int NOT NULL,
sgsID int NOT NULL,
targetLevel numeric(5, 2) NULL,
notApplicable bit NULL
)
GO

-- Set default bit column value to 0
ALTER TABLE tbl_UserTargetLevels ADD CONSTRAINT DF_tbl_UserTargetLevels_notApplicable DEFAULT 0 FOR notApplicable
GO

-- Ensure that targetLevel and notApplicable are not both NULL
ALTER TABLE tbl_UserTargetLevels ADD CONSTRAINT CK_tbl_UserTargetLevels CHECK (notApplicable IS NULL AND targetLevel IS NULL)
GO

INSERT INTO tbl_UserTargetLevels (userID, sgsID, targetLevel, notApplicable) VALUES (1, 1, NULL, 1) -- ERROR!!
GO


TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2009-08-17 : 11:02:29
Your CHECK "...And targetLevel IS NULL" is being violated by your insert. You are passing "1" which is obviously not null

EDIT:
Odd - why create columns that you want to enforces are always NULL ???

Be One with the Optimizer
TG
Go to Top of Page

R
Constraint Violating Yak Guru

328 Posts

Posted - 2009-08-17 : 11:18:06
quote:
Originally posted by TG

Your CHECK "...And targetLevel IS NULL" is being violated by your insert. You are passing "1" which is obviously not null

EDIT:
Odd - why create columns that you want to enforces are always NULL ???

Be One with the Optimizer
TG



Okay I'm still confused... I need to ensure that targetLevel and notApplicable are never NULL at the same time. Either one can be NULL on its own, but they cannot both be NULL. This is the first time I've written a constraint like this so my T-SQL is a bit rusty (to put it politely!).

Based on your reply, should the code therefore read:


ALTER TABLE tbl_UserTargetLevels ADD CONSTRAINT CK_tbl_UserTargetLevels CHECK (notApplicable IS NOT NULL AND targetLevel IS NOT NULL)
Go to Top of Page

R
Constraint Violating Yak Guru

328 Posts

Posted - 2009-08-17 : 11:20:26
Well no it shouldn't, because that isn't working either. So what should the CONSTRAINT actually say...??
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2009-08-17 : 11:44:55
a few ways. here's 2
CHECK (isnull(notApplicable, 1) + isnull(targetLevel, 1) < 2)

CHECK ((notApplicable is not null) or (targetLevel is not null))
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2009-08-17 : 11:48:38
if one must be null and the other not null (in which case it actually could have been one column) can do this
CHECK ((notApplicable is null) ^ (targetLevel is null))
Go to Top of Page

R
Constraint Violating Yak Guru

328 Posts

Posted - 2009-08-17 : 12:14:24
Thanks Russell

Your suggestions did fix the problem, however, there is another part which I overlooked originally.
The constraint should actually state that the columns cannot both be NULL at the same time, plus, they cannot both be NOT NULL at the same time!

quote:

in which case it actually could have been one column



I don't think that's possible in this instance. Both columns are containing values that are used for completely different functions within an application. Within the app though, the presence of one value stops the other being required. The app has code to catch this from happening, but I wanted to just give that little bit of extra security and get SQL Server to also watch for it happening (in case I edited the table directly, for example).

So, would this work, or is there a much simpler way...?


CHECK ((isnull(notApplicable, 1) + isnull(targetLevel, 1) <> 2) AND (isnull(notApplicable, 0) + isnull(targetLevel, 0) <> 0))
Go to Top of Page

R
Constraint Violating Yak Guru

328 Posts

Posted - 2009-08-17 : 12:32:26
No that doesn't work either. I presume therefore I need to use two separate constraints to achieve this.
I can't figure out how the both NOT NULL one would be written though...
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2009-08-17 : 12:39:16
quote:
Originally posted by russell

if one must be null and the other not null (in which case it actually could have been one column) can do this
CHECK ((notApplicable is null) ^ (targetLevel is null))



this way
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2009-08-17 : 13:16:09
So you are trying to inforce "mutual exclusivity" where exactly one value needs to be null while the other is not null.

I got a syntax error with russell's solution (above).

This works:

use tempdb
go
CREATE TABLE tbl_UserTargetLevels
(
[ID] INT IDENTITY(1,1) PRIMARY KEY,
userID int NOT NULL,
sgsID int NOT NULL,
targetLevel numeric(5, 2) NULL,
notApplicable bit NULL
)
GO

-- Set default bit column value to 0
ALTER TABLE tbl_UserTargetLevels ADD CONSTRAINT DF_tbl_UserTargetLevels_notApplicable DEFAULT 0 FOR notApplicable
GO

-- Ensure that targetLevel and notApplicable are not both NULL
ALTER TABLE tbl_UserTargetLevels ADD CONSTRAINT CK_tbl_UserTargetLevels
CHECK (coalesce(targetLevel, notapplicable) is not null and targetLevel + notapplicable is null)

GO

INSERT INTO tbl_UserTargetLevels (userID, sgsID, targetLevel, notApplicable) VALUES (1, 1, NULL, 1)
INSERT INTO tbl_UserTargetLevels (userID, sgsID, targetLevel, notApplicable) VALUES (1, 1, 1.2, null)
INSERT INTO tbl_UserTargetLevels (userID, sgsID, targetLevel, notApplicable) VALUES (1, 1, null, null)
INSERT INTO tbl_UserTargetLevels (userID, sgsID, targetLevel, notApplicable) VALUES (1, 1, 2.1, 0)

select * from tbl_UserTargetLevels

GO
drop table tbl_UserTargetLevels

OUTPUT:
Msg 547, Level 16, State 0, Line 4
The INSERT statement conflicted with the CHECK constraint "CK_tbl_UserTargetLevels". The conflict occurred in database "tempdb", table "dbo.tbl_UserTargetLevels".
The statement has been terminated.
Msg 547, Level 16, State 0, Line 5
The INSERT statement conflicted with the CHECK constraint "CK_tbl_UserTargetLevels". The conflict occurred in database "tempdb", table "dbo.tbl_UserTargetLevels".
The statement has been terminated.
ID userID sgsID targetLevel notApplicable
----------- ----------- ----------- --------------------------------------- -------------
1 1 1 NULL 1
2 1 1 1.20 NULL


EDIT:
added a line break to avoid scrolling

Be One with the Optimizer
TG
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2009-08-17 : 14:05:27
you're right. can't do it that way in check constraint. yours works, or the other way i showed.
Go to Top of Page

R
Constraint Violating Yak Guru

328 Posts

Posted - 2009-08-17 : 15:09:57
quote:

So you are trying to inforce "mutual exclusivity" where exactly one value needs to be null while the other is not null.



Yes, after writing down the allowable variations, yes, it does mean mutual exclusivity.
In your statement:
CHECK (coalesce(targetLevel, notapplicable) is not null and targetLevel + notapplicable is null)

can you please explain how targetLevel + notapplicable is null works?

Thanks!
Go to Top of Page

R
Constraint Violating Yak Guru

328 Posts

Posted - 2009-08-17 : 15:13:36
Also I get an error when I try to execute the command:

ALTER TABLE dbo.tbl_UserTargetLevels ADD CONSTRAINT CK_tbl_UserTargetLevels CHECK (coalesce(targetLevel, notapplicable) is not null and targetLevel + notapplicable is null)


The ALTER TABLE statement conflicted with the CHECK constraint "CK_tbl_UserTargetLevels". The conflict occurred in database "MyDB", table "dbo.tbl_UserTargetLevels".

Does that error not imply that the constraint is conflicting with itself??
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2009-08-17 : 15:21:32
I think the error is probably because you are trying to add the new version version of the check constraint without dropping the current one first.

As to your first question, any expression using a NULL will resolve to NULL. So if either (targetLevel or notapplicable) is null when you attempt to ADD them the result must be NULL. So that half of the check inures that at lease one of the values is NULL.

Be One with the Optimizer
TG
Go to Top of Page

R
Constraint Violating Yak Guru

328 Posts

Posted - 2009-08-17 : 15:42:45
Okay, thanks for the explanation. I think I have enough info to be getting along with now.

Thank you very much everyone for your help.
Go to Top of Page

DonAtWork
Master Smack Fu Yak Hacker

2167 Posts

Posted - 2009-08-18 : 07:23:35
quote:
Originally posted by TG

I think the error is probably because you are trying to add the new version version of the check constraint without dropping the current one first.

As to your first question, any expression using a NULL will resolve to NULL. So if either (targetLevel or notapplicable) is null when you attempt to ADD them the result must be NULL. So that half of the check inures that at lease one of the values is NULL.

Be One with the Optimizer
TG


IF you have CONCAT_NULL_YEILDS_NULL set ON. (is it ON by default? I forget.)

http://weblogs.sqlteam.com/jeffs/archive/2008/05/13/question-needed-not-answer.aspx
How to ask: http://weblogs.sqlteam.com/brettk/archive/2005/05/25.aspx

For ultra basic questions, follow these links.
http://www.sql-tutorial.net/
http://www.firstsql.com/tutor.htm
http://www.w3schools.com/sql/default.asp
Go to Top of Page
   

- Advertisement -