我有一个有 2 列(A as bool
和B as text
)的表,这些列可以是:
- 两者都是空的
- 如果 A 为 False,则 B 应为空
- 如果 A 为 True,则 B 不应为空
有规则。我想创建一个存储过程或函数来在添加或更新行时检查这些规则(通过触发器)。存储过程或函数哪个更好?如果是函数,是什么类型?一般来说,哪个变体是最好的(返回布尔值或其他方式等)?
我有一个有 2 列(A as bool
和B as text
)的表,这些列可以是:
有规则。我想创建一个存储过程或函数来在添加或更新行时检查这些规则(通过触发器)。存储过程或函数哪个更好?如果是函数,是什么类型?一般来说,哪个变体是最好的(返回布尔值或其他方式等)?
我认为您在使用CHECK
Constraint。
例子:
ALTER TABLE Xxx
ADD CONSTRAINT chk_Xxx
CHECK ( (A IS NULL AND B IS NULL)
OR (A = 0 AND B IS NULL)
OR (A = 1 AND B IS NOT NULL)
) ;
我会使用连接到 UDF 的 CHECK CONSTRAINT。
这是一个愚蠢的例子,验证如果你插入一个人,他们的年龄将大于 17。
if NOT exists (select * from sysobjects
where id = object_id('dbo.udfOlderThan17Check') and sysstat & 0xf = 0)
BEGIN
print 'Creating the stubbed version of dbo.udfOlderThan17Check'
EXEC ( 'CREATE FUNCTION dbo.udfOlderThan17Check ( @j as smallint ) RETURNS bit AS BEGIN RETURN 0 END')
END
GO
ALTER FUNCTION dbo.udfOlderThan17Check ( @Age smallint )
RETURNS bit AS
BEGIN
declare @exists int
select @exists = 0
if ( @Age IS NULL )
BEGIN
select @exists = 1 -- NULL VALUES SHOULD NOT BLOW UP THE CONSTRAINT CHECK
END
if ( @exists = 0 )
BEGIN
if @Age > 17
begin
select @exists = 1
end
END
return @exists
END
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[Person]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
DROP TABLE [dbo].[Person]
END
GO
CREATE TABLE [dbo].[Person]
(
PersonUUID [UNIQUEIDENTIFIER] NOT NULL DEFAULT NEWSEQUENTIALID()
, Age smallint not null
)
GO
ALTER TABLE dbo.Person ADD CONSTRAINT PK_Person
PRIMARY KEY NONCLUSTERED (PersonUUID)
GO
ALTER TABLE dbo.Person
ADD CONSTRAINT [CK_Person_AgeValue] CHECK ([dbo].[udfOlderThan17Check]( [Age] ) != 0)
GO
以下是一些“测试”:
INSERT INTO dbo.Person (Age) values (33)
INSERT INTO dbo.Person (Age) values (16)
INSERT INTO dbo.Person (Age) select 333 UNION select 58
INSERT INTO dbo.Person (Age) select 444 UNION select 4
select * from dbo.Person