I tried to add a Check Constraint and I have only failed so far. What would be the way to get around this:
Msg 1046, Level 15, State 1, Line 6
Subqueries are not allowed in this context. Only scalar expressions are allowed.
This is the code:
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条答案
按热度按时间af7jpaap1#
SQL Server does not currently support subqueries for CHECK CONSTRAINTs.
As you have discovered, there can be trouble with CHECK constraints involving UDFs when attempting to circumvent the subquery limitation.
The alternative constraint implementation strategies are triggered procedural and embedded procedural. The former is preferred because, in common with declarative constraints, they cannot be circumvented.
Implementing a triggered procedural strategy that is well optimized and handles concurrency issues is non-trivial but still doable. I highly recommend the book Applied Mathematics for Database Professionals By Lex de Haan, Toon Koppelaars, chapter 11 (the code examples are Oracle but can be easily ported to SQL Server).
4uqofj5v2#
As others have mentioned already, this type of Check constraints is not yet implemented in SQL-Server. Besides triggers, you could also examine the possibility of changing the table's design.
A possible alternative includes storing the previous interval end-date in every row. See Storing intervals of time with no overlaps for details. The enforcing constraints are simple but there are complications on the way you'll have to deal with Inserts/Deletes/Updates on the table.
Another possibility would be to store not one row (with the start and end-date) for a discount as you do now but a whole series of rows (one for every date of the discount interval). The enforcing constraints will be even simpler but you'll have a lot of rows instead of every one of your current table.