Question


I am curious to know is it possible to create a conditional not null constraint in sql? In otherwords is it possible to create a constraint such that a column B can be null as long column A contains lets say 'NEW' but if the contents of column A changes to something else then column B is no longer allowed to be null?
And to extend on that, it is then possible to make it so that column B must be null or empty as long as column A says 'NEW'?
Thanks All :D

Was it helpful?

Solution

This is perfectly fine for CONSTRAINT CHECK. Just do this:

Requirement:

is it possible to create a constraint such that a column B can be null as long column A contains lets say 'NEW' but if the contents of column A changes to something else then column B is no longer allowed to be null?

Note the phrase: column B can be null

Solution:

create table tbl
(
    A varchar(10) not null,
    B varchar(10),

    constraint uk_tbl check
    (
      A = 'NEW' -- B can be null or not null: no need to add AND here
      OR (A <> 'NEW' AND B IS NOT NULL)
    )
);

You can simplify it further:

create table tbl
(
    A varchar(10) not null,
    B varchar(10),

    constraint uk_tbl check
    (
      A = 'NEW' 
      OR B IS NOT NULL
    )
);

Requirement mutually incompatible to requirement above:

And to extend on that, it is then possible to make it so that column B must be null or empty as long as column A says 'NEW'?

Note the phrase: column B must be null

create table tbl
(
    A varchar(10) not null,
    B varchar(10),

    constraint uk_tbl check
    (
      (A = 'NEW' AND B IS NULL)
      OR A <> 'NEW'
    )
);

Could be simplified with this, simpler but might not be as readable as above though:

create table tbl
(
    A varchar(10) not null,
    B varchar(10),

    constraint uk_tbl check
    (
      A <> 'NEW'
      OR B IS NULL
    )
);

OTHER TIPS

I think your first stated requirement is:

IF ( B IS NULL ) THEN ( A = 'NEW' )

Apply the implication rewrite rule:

IF ( X ) THEN ( Y )   <=>   ( NOT ( X ) OR ( Y ) )

In your case;

( NOT ( B IS NULL ) OR ( A = 'NEW' ) )

Minor rewrite to take advantage of SQL syntax:

( B IS NOT NULL OR A = 'NEW' )

Your second stated ("extend") requirement:

IF ( A = 'NEW' ) THEN ( B IS NULL )

Apply rewrite rule:

( NOT ( A = 'NEW' ) OR ( B IS NULL ) )

Minor rewrite:

( A <> 'NEW' OR B IS NULL )

Edit: as mentioned in the other answers, a CHECK is the best method, not the trigger I originally suggested. Original text follows:


As dbaseman suggests, triggers are the way to go (not so). Try something like this (untested):

CREATE OR REPLACE TRIGGER test
  BEFORE UPDATE ON table1
FOR EACH ROW
WHEN (new.A = 'NEW' and new.B IS NOT NULL)
   RAISE_APPLICATION_ERROR (
     num=> -20001,
     msg=> 'B must be NULL for new rows (A = NEW)'
);

Per onedaywhen, this answer is criminally wrong, and an abomination. You can use a CHECK constraint. http://msdn.microsoft.com/en-us/library/ms188258.aspx

There's not a way to make conditional constraints. You should, however be able to do the job using a trigger. That's what they're for.

http://msdn.microsoft.com/en-us/library/ms189799.aspx

CREATE TRIGGER MyTable.ConditionalNullConstraint ON MyTable.ColumnB
AFTER INSERT
AS
IF EXISTS (SELECT *
    FROM inserted
    WHERE A <> 'NEW' AND B IS NULL
    )
BEGIN
    RAISERROR ('if A is ''NEW'' then B cannot be NULL', 16, 1);
    ROLLBACK TRANSACTION;
END;
GO

Note that in the query you'll want to reference inserted which is a special object that behaves like a table, and lets you reference the row(s) that caused the trigger.

Of course, in this example you'd need to handle AFTER UPDATE also to enforce the constraint, but that's the general idea.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top