Sql Conditional Not Null Constraint

冷暖自知 提交于 2019-12-09 04:18:13

问题



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


回答1:


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
    )
);



回答2:


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 )



回答3:


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)'
);



回答4:


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.



来源:https://stackoverflow.com/questions/10273750/sql-conditional-not-null-constraint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!