Подтвердить что ты не робот

Sql Условное не полное ограничение


Мне любопытно узнать, возможно ли создать условное, но не нулевое ограничение в sql? В других словах можно создать ограничение таким образом, чтобы столбец B мог быть нулевым, поскольку длинный столбец A содержит позволяет сказать "NEW", но если содержимое столбца A изменяется на что-то еще, тогда столбцу B больше не разрешено быть нулевым?
И чтобы расширить это, тогда можно сделать так, чтобы столбец B был пустым или пустым, если столбец A говорит "NEW"?
Спасибо всем: D

4b9b3361

Ответ 1

Это отлично подходит для КОНТРОЛЬНОЙ ПРОВЕРКИ. Просто сделайте следующее:

Требование:

можно создать ограничение таким образом, чтобы столбец B мог быть нулевым поскольку длинный столбец A содержит позволяет сказать "NEW", но если содержимое столбца Изменения в чем-то еще, а затем столбце B больше не разрешено нуль?

Обратите внимание на фразу: столбец B может быть null

Решение:

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

Вы можете упростить его:

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

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

Требование, несовместимое с требованиями выше:

И чтобы расширить это, тогда можно сделать так, чтобы столбец B должен быть пустым или пустым, если столбец A говорит "NEW"?

Обратите внимание на фразу: столбец B должен быть 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'
    )
);

Может быть упрощено с этим, проще, но может быть не так читаемо, как указано выше:

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

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

Ответ 2

Изменить: как упоминалось в других ответах, CHECK - лучший метод, а не триггер, который я изначально предложил. Исходный текст следует:


Как предполагает dbaseman, триггеры - это путь (не так). Попробуйте что-то вроде этого (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)'
);

Ответ 3

Я думаю, что ваше первое заявленное требование:

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

Примените правило перезаписи импликации:

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

В вашем случае

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

Мало переписать, чтобы воспользоваться синтаксисом SQL:

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

Ваше второе заявленное требование ( "продлить" ):

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

Применить правило перезаписи:

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

Незначительный переписывать:

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

Ответ 4

В первый раз, этот ответ преступно ошибочен и мерзость. Вы можете использовать ограничение ПРОВЕРИТЬ. http://msdn.microsoft.com/en-us/library/ms188258.aspx

Там нет способа сделать условные ограничения. Однако вы должны выполнять работу с помощью триггера. Для чего они предназначены.

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

Обратите внимание, что в запросе вы хотите ссылаться на вставленный, который является особым объектом, который ведет себя как таблица, и позволяет ссылаться на строки, вызвавшие триггер.

Конечно, в этом примере вам нужно будет обрабатывать ПОСЛЕ ОБНОВЛЕНИЯ также для принудительного применения ограничения, но это общая идея.