多表检查约束

时间:2018-02-24 00:03:14

标签: sql sql-server tsql sql-server-2012 constraints

是否可以根据其他两个表中的条件添加检查约束?我有三个表:集合,会话和session_detail。我的目标是从同一个集合中使用相同的会话类型阻止多个结构出现在session_detail中。

将我到目前为止的功能应用于 sessions 表检查唯一的集合和会话,但不检查唯一的结构。

ALTER FUNCTION [dbo].[checkSessionType](@collection as varchar(max), @type as varchar(max))  
RETURNS int  
AS   
BEGIN  
DECLARE @sessionType varchar(max) 

SELECT @sessionType = case when @type = 'R' then @type When @type = 'T' then @type END
DECLARE @retval int

SELECT @retval = COUNT(*) 
FROM (SELECT a.structure_id, b.collection, b.session_type 
        FROM session_detail a 
        INNER JOIN sessions b ON a.session_id = b.session_id 
        WHERE b.collection = @collection 
        AND b.session_Type = @sessionType 
) AS tempResults
RETURN @retval  
END;   

这是表格的简化版本:

collections(collection)
sessions(session_id, collection, session_type)
session_detail(detail_id, session_id, structure_id)

那么,只要具有不同的会话类型,我怎么能让结构多次出现在同一个集合中呢?我可以用触发器做这个,但我更喜欢约束。

2 个答案:

答案 0 :(得分:2)

您可以使用索引视图,例如:

CREATE VIEW v_session_detail
WITH SCHEMABINDING AS
SELECT sd.structure_id, s.collection, s.session_type
FROM dbo.session_detail sd
INNER JOIN dbo.sessions s ON s.session_id=sd.session_id
GO
CREATE UNIQUE CLUSTERED INDEX PK_v_session_detail ON v_session_detail(structure_id, collection, session_type)

答案 1 :(得分:1)

如果您想将控制作为检查约束:

CREATE FUNCTION [dbo].[checkSessionType](@session_id as INT, @structure_id as INT)  
RETURNS int  
AS   
BEGIN  

DECLARE @retval int

SELECT @retval = COUNT(*)
FROM sessions a 
INNER JOIN session_detail b ON a.session_id = b.session_id 
WHERE b.structure_id = @structure_id 
AND b.session_id = @session_id
GROUP BY a.collection, a.session_type, b.structure_id

RETURN @retval  
END

GO

ALTER TABLE [session_detail] ADD CONSTRAINT ck_session_detail CHECK ([dbo].[checkSessionType](session_id, structure_id) <= 1)

同样,您还需要在sessions表上进行检查。为此,您可以创建另一个函数,仅用于检查sessions表或自定义上一个表以适应两种情况:

CREATE FUNCTION [dbo].[checkSessionType](@session_id as INT, @collection as INT, @structure_id as INT)  
RETURNS int  
AS   
BEGIN  

DECLARE @retval int

SELECT @retval = COUNT(*)
FROM sessions a 
INNER JOIN  session_detail b ON a.session_id = b.session_id 
WHERE b.structure_id = ISNULL(@structure_id, b.structure_id)
AND a.collection = ISNULL(@collection, a.collection)
AND b.session_id = @session_id
GROUP BY a.collection, a.session_type, b.structure_id

RETURN @retval  
END

GO

ALTER TABLE [sessions] ADD CONSTRAINT ck_sessions CHECK ([dbo].[checkSessionType](session_id, collection, null) <= 1)
ALTER TABLE [session_detail] ADD CONSTRAINT ck_session_detail CHECK ([dbo].[checkSessionType](session_id, null, structure_id) <= 1)