为什么这个Check约束不起作用?

时间:2013-11-26 09:09:36

标签: sql sql-server sql-server-2005 check-constraints check-constraint

我在SQL Server 2005中创建了一个检查约束,但是此检查约束不起作用。 SQL Server Management Studio通过insert语句告诉我以下消息:

  

Msg 547,Level 16,State 0,Line 1
  INSERT语句与CHECK约束“MY_CHECK_CONSTAINT”冲突。冲突发生在数据库“MY_DB”,表“dbo.MY_TABLE”,列“MY_COLUMN”中。

我已使用以下代码添加了检查约束:

ALTER TABLE MY_TABLE WITH NOCHECK
ADD CONSTRAINT CK_MY_CHECK_CONSTRAINT CHECK (dbo.MY_FUNCTION(MY_PARAMETER)<1)

调用函数“MY_FUNCTION”返回一个int。

我的目标是,如果我的函数返回一个小于1的int,则insert语句可以成功完成,如果返回值大于0,则必须终止insert语句。

我现在的问题是我的函数返回值0但是insert语句总是被终止。我做错了什么?

我的功能代码如下:

CREATE FUNCTION MY_FUNCTION(@MY_PARAMETER uniqueidentifier) 
RETURNS int 
AS 
BEGIN 
    declare @return int = 0
    SET @return = (SELECT COUNT(MY_COLUMN) FROM MY_TABLE WHERE MY_COLUMN= @MY_PARAMETER )
return @return 
END 

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

我能够100%重现您的问题。试试这个新的 以下示例。现在我的table table1是空的,我无法插入
任何数字进入它:)非常有趣的情况,绝对是 和你的一样,我相信。

“也许当您的UDF代码被执行时,它已经看到了同样的情况 你想要插入的行(它看到它在表中)。
我不知道内部工作,现在没有太多时间来检查它。
但这可能是问题所在。我的UDF不会根据某些执行检查 选择在同一张表中,这是在概念上不同的 你的例子和我的例子。“

好的,经过5分钟的研究,结果证明我的猜测是对的 当你的UDF被调用时,它会看到你正在尝试的行 插入。

请参阅此处接受的答案。

Check constraint UDF with multiple input parameters not working

所以 - 神秘揭秘,似乎:)


--- 1 ---

USE [test]
GO

/****** Object:  UserDefinedFunction [dbo].[ContainsNumber]    Script Date: 11/26/2013 07:06:41 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[ContainsNumber]
(
        @number int
)
RETURNS INT AS

BEGIN

declare @result int

select @result = count(*)
from test.dbo.table1
where
number = @number

if (@result > 0) 
begin
    set @result = 1
end

return @result

END


GO



--- 2 ---

USE [test]
GO

/****** Object:  Table [dbo].[table1]    Script Date: 11/26/2013 07:06:33 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[table1](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [number] [int] NULL,
 CONSTRAINT [PK_table1] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[table1]  WITH CHECK ADD  CONSTRAINT [CK_table1] CHECK  (([dbo].[ContainsNumber]([number])=(0)))
GO

ALTER TABLE [dbo].[table1] CHECK CONSTRAINT [CK_table1]
GO

答案 1 :(得分:0)

1)也许你可以在你的代码中尝试这个:

SELECT @return = COUNT(MY_COLUMN) 
FROM MY_TABLE WHERE MY_COLUMN = @MY_PARAMETER

而不是你做的。

2)尝试命名变量而不是@return,例如@result。

3)尝试在正常通话之外行走你的功能。

4)另外,您可能想在下面尝试此测试。 我没有看到任何问题...但好的, 它不是和你的100%相同。

下面的检查约束可以正常使用 我的用户定义函数 IsEvenNumber。

----- 1 -----

USE [test]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO



CREATE FUNCTION [dbo].[IsEvenNumber]
(
        @number int
)
RETURNS INT AS

BEGIN

declare @result int

set @result = 1

if (((@number) % 2) <> 0)
begin
    set @result = 0
end


return @result


END



GO




----- 2 -----


USE [test]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[table1](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [number] [int] NULL,
 CONSTRAINT [PK_table1] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[table1]  WITH CHECK ADD  CONSTRAINT [CK_Table1] CHECK  (([dbo].[IsEvenNumber]([number])<(1)))
GO

ALTER TABLE [dbo].[table1] CHECK CONSTRAINT [CK_Table1]
GO



----- 3 -----


insert into table1(number) values (3) -- OK

insert into table1(number) values (10) -- FAILED

insert into table1(number) values (0) -- FAILED

insert into table1(number) values (5) -- OK