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

Jam*_*mes 11 sql sql-server-2008

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

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

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

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

jpw*_*jpw 16

正如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); 
Run Code Online (Sandbox Code Playgroud)


Mar*_*ith 12

您可以使用标量UDF,但在检查约束中使用那些已经记录良好的问题(例如,查看包含在CHECK约束中的标量UDF非常慢,并且可能因多行更新快照隔离而失败:对完整性的威胁?系列.

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

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

CREATE TABLE dbo.TwoNums
  (
     Num INT PRIMARY KEY
  )

INSERT INTO dbo.TwoNums
VALUES      (1),
            (2) 
Run Code Online (Sandbox Code Playgroud)

然后是视图定义

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 
Run Code Online (Sandbox Code Playgroud)

并且View上有一个独特的索引

CREATE UNIQUE CLUSTERED INDEX [UIX_PreventOverCapacity (Venueid, EventId, Expected, Capacity)]
  ON dbo.PreventOverCapacity(Venueid, EventId, Expected, Capacity) 
Run Code Online (Sandbox Code Playgroud)

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

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

  • @IanKemp 那么你就错了。问题是完全相同的。它们仍然逐行评估,因此可能会因中间状态违反约束而失败,尽管语句末尾的状态不会违反约束,并且您仍然需要考虑快照隔离并添加适当的锁定提示。使用索引视图意味着您以声明方式定义它,并利用正确编写的产品功能来避免这些陷阱 (2认同)