Мне любопытно узнать, возможно ли создать условное, но не нулевое ограничение в sql? В других словах можно создать ограничение таким образом, чтобы столбец B мог быть нулевым, поскольку длинный столбец A содержит позволяет сказать "NEW", но если содержимое столбца A изменяется на что-то еще, тогда столбцу B больше не разрешено быть нулевым?
И чтобы расширить это, тогда можно сделать так, чтобы столбец B был пустым или пустым, если столбец A говорит "NEW"?
Спасибо всем: D
Sql Условное не полное ограничение
Ответ 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
Обратите внимание, что в запросе вы хотите ссылаться на вставленный, который является особым объектом, который ведет себя как таблица, и позволяет ссылаться на строки, вызвавшие триггер.
Конечно, в этом примере вам нужно будет обрабатывать ПОСЛЕ ОБНОВЛЕНИЯ также для принудительного применения ограничения, но это общая идея.