具有检查约束的自定义函数SQL Server 2008

时间:2014-11-01 21:43:11

标签: sql sql-server-2008

我使用SQL Server 2008,我有两个现有表venuesevents

我正在尝试使用检查约束创建自定义函数,以确保event_expected_attendance表中events列中的整数始终小于或等于venue_max_capacity venues表中的整数。

我正在努力使用自定义函数的语法以及join语句,因为检查约束在两个表之间。

感谢您的帮助!我会尽快回答任何其他问题。

2 个答案:

答案 0 :(得分:13)

正如Martin Smith所说,使用UDF的检查约束有一些问题,可能会对性能产生负面影响,但如果你想尝试它,那么这段代码应该可以工作:

CREATE FUNCTION dbo.CheckVenueCapacity (@venue_id int, @capacity int)
RETURNS int
AS 
BEGIN
  DECLARE @retval int
    SELECT @retval = CASE WHEN venue_max_capacity >= @capacity THEN 0 ELSE 1 END
    FROM venues
    WHERE venue_id = @venue_id 
  RETURN @retval
END;
GO

ALTER TABLE events 
  ADD CONSTRAINT chkVenueCapacity 
  CHECK (dbo.CheckVenueCapacity(event_venue_id, event_expected_attendance) = 0); 

答案 1 :(得分:11)

您可以为此使用标量UDF,但在检查约束中使用这些UDF会有很好的记录问题(例如,请参阅Scalar UDFs wrapped in CHECK constraints are very slow and may fail for multirow updatesSnapshot isolation: A threat for integrity?系列。

也可以让数据库引擎使用索引视图强制执行此操作

它需要一个包含2行作为CTE的帮助器表,并且在索引视图中不允许UNION。我们的想法是视图定义应始终返回零行,如果存在违规,则会将所返回的行加倍。因此导致违反视图上的唯一约束并导致错误发生并且语句失败。

CREATE TABLE dbo.TwoNums
  (
     Num INT PRIMARY KEY
  )

INSERT INTO dbo.TwoNums
VALUES      (1),
            (2) 

然后是视图定义

CREATE VIEW dbo.PreventOverCapacity
WITH SCHEMABINDING
AS
  SELECT V.Venueid,
         E.EventId,
         E.Expected,
         V.Capacity
  FROM   dbo.Venues V
         JOIN dbo.Events E
           ON E.venueid = V.venueid
              AND E.Expected > V.Capacity
         CROSS JOIN dbo.TwoNums 

视图上的唯一索引

CREATE UNIQUE CLUSTERED INDEX [UIX_PreventOverCapacity (Venueid, EventId, Expected, Capacity)]
  ON dbo.PreventOverCapacity(Venueid, EventId, Expected, Capacity) 

包含所有四列的原因是所有必需的值都显示在错误消息中。

  

无法在对象'dbo.PreventOverCapacity'中插入重复的键行   具有唯一索引'UIX_PreventOverCapacity(Venueid,EventId,   预期,容量)'   重复键值为(1,97,110,100)。