问题
I have a check constraint on a table in my DB. My understanding of a check is it sets a logical condition that must be true for records in a table.
USE [myDB]
GO
ALTER TABLE [dbo].[myTable] WITH CHECK ADD CONSTRAINT [oneProgramPerTest] CHECK (([dbo].[howManyProgPerTest]([TestId])<(2)))
GO
ALTER TABLE [dbo].[myTable] CHECK CONSTRAINT [oneProgramPerTest]
GO
But I am able to do an update to the table that breaks the constraint. After the update, this query returns 9 records:
select COUNT (*) from myDB.dbo.myTable where myDB.[dbo].[howManyProgPerTest](testID)>1
What might be going on?
回答1:
Beware using UDFs in check constraints for this reason. This blog post describes your issue. To summarize:
(A UDF) will on the surface do its job, as long as you
INSERT
into the table. But if you update a row and only set the otherColumn for some row from 0 to 1, then the check constraint will not be checked.The optimizer is smart enough to understand that the update doesn't change anything that we refer to in our CHECK constraint, so why bother checking the constraint?
End result here is that the constraint doesn't do what we want it to do. Use a trigger instead (or some other method).
(Emphasis added)
回答2:
If I may, based on the name of your constraint, are you trying to ensure that there is only one program per test? If both the program and the test are available in the same table, add a unique constraint.
来源:https://stackoverflow.com/questions/15438184/why-is-t-sql-allowing-me-to-violate-a-check-constraint-that-uses-a-udp