函数+check 解决多表数据间的约束
--需求
/*
有以下两个资料表:
Restable
id int
IStatus bit
RestableS
id int
要求:当RestableS表中存在与Restable相同的ID时,Restable表的IStatus字段不允许更改值为0,这个约束应该如何实现?
*/
--建立测试表
IF OBJECT_ID('Restable') IS NOT NULL DROP TABLE Restable
GO
CREATE TABLE Restable (id int,IStatus bit)
GO
IF OBJECT_ID('RestableS') IS NOT NULL DROP TABLE RestableS
GO
CREATE TABLE RestableS (id int)
--创建函数
if object_id('f_checkRS') is not null drop function f_checkRS
go
create function f_checkRS(@ID int)
returns INT
as
begin
declare @r int
if exists (select 1 from RestableS where ID=@ID)
set @r=0
else
set @r=2
return @r
end
go
--创建约束:
--不指定约束名,创建check
--alter table Restable add check(IStatus<>dbo.f_checkRS(id))
--指定约束名,创建check
alter table Restable add Constraint statusCK check(IStatus<>dbo.f_checkRS(id))
go
--测试
insert RestableS values(1)
--(1 行受影响)
insert Restable values(1,0)
--结果
/*
消息 547,级别 16,状态 0,第 4 行
INSERT 语句与 CHECK 约束"statusCK"冲突。该冲突发生于数据库"master",表"dbo.Restable"。
*/
insert Restable values(1,1)
--(1 行受影响)
insert Restable values(2,0)
--(1 行受影响)
insert Restable values(3,null)
--(1 行受影响)
insert RestableS values(2)
--(1 行受影响)
--如果说 Restable 表先插入数据,则约束始终符合
--当 RestableS 中插入了与其id相同的数据后,不影响 Restable 表以前插入的数据
--用下面语句检测数据是否符合约束
alter table Restable with check check constraint statusCK
/*
消息 547,级别 16,状态 0,第 1 行
ALTER TABLE 语句与 CHECK 约束"statusCK"冲突。该冲突发生于数据库"master",表"dbo.Restable"。
*/