我很想知道是否可以在 sql 中创建条件非空约束?换句话说,是否可以创建一个约束,使得 B 列可以为空,只要 A 列包含让我们说“新”,但如果 A 列的内容更改为其他内容,那么 B 列不再允许为空?
为了扩展这一点,只要 A 列显示“新”,就有可能使 B 列必须为空或为空?
谢谢大家 :D
4 回答
这对于 CONSTRAINT CHECK 来说非常好。只需这样做:
要求:
是否可以创建一个约束,使得 B 列可以为空,只要 A 列包含让我们说“新”,但如果 A 列的内容更改为其他内容,则 B 列不再允许为空?
注意这句话:B 列可以为空
解决方案:
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
)
);
要求与上述要求互不兼容:
为了扩展这一点,只要 A 列显示“新”,就有可能使 B 列必须为空或为空?
注意这句话:B 列必须为空
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
)
);
我认为您的第一个要求是:
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 )
编辑:如其他答案中所述, CHECK 是最好的方法,而不是我最初建议的触发器。原文如下:
正如 dbaseman 建议的那样,触发器是要走的路(不是这样)。尝试这样的事情(未经测试):
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,这个答案在犯罪上是错误的,而且令人憎恶。您可以使用CHECK约束。 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
请注意,在查询中,您需要引用插入的对象,它是一个行为类似于表的特殊对象,并允许您引用导致触发器的行。
当然,在此示例中,您还需要处理AFTER UPDATE以强制执行约束,但这是一般的想法。