检查约束 - 在此上下文中不允许子查询

问题描述 投票:0回答:2

我尝试添加一个检查约束,但到目前为止我只失败了。有什么方法可以解决这个问题:

消息 1046,第 15 级,状态 1,第 6 行

在此上下文中不允许子查询。仅标量表达式 是允许的。

这是代码:

ALTER TABLE dbo.PropertySeasonDiscount ADD CONSTRAINT
[CC_PropertySeasonDiscount_MadeFrom_MadeTo]
CHECK (
    (SELECT COUNT(PropertySeasonDiscountId) FROM dbo.PropertySeasonDiscounts apsdeb 
        WHERE 
            (apsdeb.PropertySeasonId = PropertySeasonId) AND
            (
                (apsdeb.ValidForReservationsMadeTo >= ValidForReservationsMadeFrom AND ValidForReservationsMadeFrom >= apsdeb.ValidForReservationsMadeFrom) OR
                (apsdeb.ValidForReservationsMadeFrom <= ValidForReservationsMadeTo AND ValidForReservationsMadeTo <= apsdeb.ValidForReservationsMadeTo)
            )
    ) = 0
);
sql sql-server sql-server-2008 t-sql constraints
2个回答
11
投票

SQL Server 目前不支持 CHECK CONSTRAINT 的子查询。

正如您所发现的,在尝试规避子查询限制时,涉及 UDF 的 CHECK 约束可能会出现问题。 替代约束实现策略是

触发程序

嵌入式程序。前者是首选,因为与声明性约束一样,它们无法被规避。 实现经过良好优化并处理并发问题的触发程序策略并非易事,但仍然可行。我强烈推荐这本书

Lex de Haan、Toon Koppelaars 所著的《数据库专业人员的应用数学》

,第 11 章(代码示例是 Oracle,但可以轻松移植到 SQL Server)。


3
投票

一种可能的替代方案包括在每一行中存储先前的间隔结束日期。有关详细信息,请参阅

存储不重叠的时间间隔

。强制约束很简单,但处理表上的插入/删除/更新的方式却很复杂。 另一种可能性是不像现在那样存储折扣的一行(包含开始日期和结束日期),而是存储一系列行(一个对应折扣间隔的每个日期)。强制约束将更加简单,但您将拥有很多行,而不是当前表中的每一行。

© www.soinside.com 2019 - 2024. All rights reserved.