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

时间:2012-03-15 15:01:35

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

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

  

Msg 1046,Level 15,State 1,Line 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
);

2 个答案:

答案 0 :(得分:11)

SQL Server目前不是support subqueries for CHECK CONSTRAINTs

正如您所发现的,在尝试绕过子查询限制时,可能会有trouble with CHECK constraints涉及UDF。

替代约束实现策略是触发的过程嵌入式过程。前者是首选,因为与声明性约束一样,它们不能被规避。

实现一个经过充分优化并处理并发问题的触发式过程策略非常重要但仍然可行。我强烈推荐这本书Applied Mathematics for Database Professionals By Lex de Haan, Toon Koppelaars,第11章(代码示例是Oracle,但可以很容易地移植到SQL Server)。

答案 1 :(得分:3)

正如其他人已经提到的,这种类型的Check约束尚未在SQL-Server中实现。除了触发器,您还可以检查更改表格设计的可能性。

可能的替代方案包括在每一行中存储前一个间隔结束日期。有关详细信息,请参阅Storing intervals of time with no overlaps。强制约束很简单,但是你必须处理表格中的插入/删除/更新的方式也很复杂。

另一种可能性是,不像现在那样存储折扣(包括开始日期和结束日期),而是存储整个系列的行(每个日期的折扣间隔一行)。强制约束将更加简单,但您将拥有大量行而不是当前表中的每一行。