我很想知道是否有可能在sql中创建一个条件非空约束?换句话说,可以创建一个约束,使得列B可以为空,因为列A包含让我们说“新”,但如果列A的内容更改为其他内容,则不再允许列B为空?
并且为了扩展它,那么只要列A表示“新”,就可以使列B必须为空或空?
谢谢大家:D
答案 0 :(得分:28)
这对于CONSTRAINT CHECK来说非常好。就这样做:
要求:
是否可以创建约束,使列B可以为空 因为列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
)
);
要求与上述要求互不兼容:
为了扩展,可以使它成为B列 只要列A表示“新”,就必须为空或空?
请注意短语: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
)
);
答案 1 :(得分:1)
编辑:如其他答案所述,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)'
);
答案 2 :(得分:1)
我认为你的第一个要求是:
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 )
答案 3 :(得分:0)
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
请注意,在查询中,您需要引用 inserted ,这是一个行为类似于表的特殊对象,并允许您引用导致触发的行。
当然,在这个例子中,您还需要处理 AFTER UPDATE 来强制执行约束,但这是一般的想法。