views:

40

answers:

1

Hi folks,

I wish to add some type of business logic constraint to a table, but not sure how / where.

I have a table with the following fields.

  • ID INTEGER IDENTITY
  • HubId INTEGER
  • CategoryId INTEGER
  • IsFeatured BIT
  • Foo NVARCHAR(200)

etc.

So what i wish is that you can only have one featured thingy, per hubId + categoryId.

eg.
1, 1, 1, 1, 'blah'  -- Ok.
2, 1, 2, 1, 'more blah' -- Also Ok
3, 1, 1, 1, 'aaa' -- constraint error
4, 1, 1, 0, 'asdasdad' -- Ok.
5, 1, 1, 0, 'bbbb' -- Ok.

etc.

so the third row to be inserted would fail because that hub AND category already have a featured thingy.

Is this possible?

+3  A: 

You use a database constraint to protect data. To me, business logic is calculations or complex logic or row-by-row processing: not a flavour of unique constraint

In this case:

  1. you can use a trigger to check after the insert
  2. define an indexed view filtering IsFeatured = 1 to on HubId, CategoryId, IsFeatured
  3. use a filtered index because you have SQL Server 2008 (which is similar to an indexed view)

I'd go for option 3, personally

PS: where is articleID you mentioned?

And this question to: Combining the UNIQUE and CHECK constraints

Edit:

Basically, you'd do

CREATE UNIQUE INDEX IX_Foo ON Mytable (HubId, CategoryId) WHERE IsFeatured = 1

So uniqueness is now checked on (HubId, CategoryId) only for the subset of data where IsFeatured = 1

gbn
articleId was a mistake. i've fixed it up, above. So .. a filtered index .. that sounds interesting ... brb (reads up about it).. hmmm. i think my head just poped. Can u elaborate on the filtered index? eg. is this a 'subset of data' or a 'Heterogeneous data' ? I feel so stupid :(
Pure.Krome
.. and because this is an index, i still need to have the AFTER insert (and update) trigger, right? (and index only speeds up the select query, in the trigger).
Pure.Krome
.. and what about using a Check Constraint + a filtered index? (I thought check constraints should be used over triggers, if possible)
Pure.Krome
@Pure.Krome: the index enforces the uniqueness you want by only allowing unique combinations of HubId, CategoryId where isfeatured = 1. When isfeatured = 0, it is not enforced. You **do not** need a trigger or check constraint if you use a filtered index
gbn
@gbn awesomesauce!! confirmed. Not only do i get an index (to help with query speed) but it's _ALSO_ offers constraining! Who's your Daddy??!! (and what does he do). Cheers mate!
Pure.Krome
Oh now that's a nice use for filtered indexes.
Meff