为啥这个 Check 约束不起作用?
Posted
技术标签:
【中文标题】为啥这个 Check 约束不起作用?【英文标题】:Why doesn't this Check constraint work?为什么这个 Check 约束不起作用? 【发布时间】:2013-11-26 09:09:36 【问题描述】:我在 SQL Server 2005 中创建了一个检查约束,但是这个检查约束不起作用。 SQL Server Management Studio 通过插入语句告诉我以下消息:
消息 547,第 16 级,状态 0,第 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 语句可以成功完成,如果返回值大于 0 则插入语句必须终止。
我现在的问题是我的函数返回值 0 但插入语句总是终止。我做错了什么?
我的函数代码如下:
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
感谢您的帮助。
【问题讨论】:
错在你的假设函数返回0是不正确的。但是我们无法告诉您为什么它不正确,因为您没有向我们展示它的代码。 我现在已经添加了我的函数代码。希望对您有所帮助。 只需在MY_COLUMN
上添加一个唯一约束。不要为此尝试使用带有标量 UDF 的检查约束。
嗨 Martin,我不能使用唯一约束,因为 MY_COLUMN 可以为 NULL。
【参考方案1】:
我能够 100% 重现您的问题。试试这个新的 下面的例子。现在我的表 table1 是空的,我无法插入 任何数字进入它:) 非常有趣的情况,绝对是 和你一样,我相信。
“也许当你的 UDF 代码被执行时,它已经看到了同样的 您只是尝试插入的行(它看到它在表中)。 我不知道内部工作原理,现在没有太多时间检查它。 但这可能是问题所在。我的 UDF 不执行基于某些 的检查 SELECT 在同一张表中,这就是 你的榜样和我的榜样。”
好的,经过 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
【讨论】:
非常感谢您的帮助 :) 现在一切正常。这就是解决方案。【参考方案2】:1) 也许你可以在你的代码中试试这个:
SELECT @return = COUNT(MY_COLUMN)
FROM MY_TABLE WHERE MY_COLUMN = @MY_PARAMETER
而不是你所做的。
2) 尝试将变量命名为不是 @return 而是例如@结果。
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
【讨论】:
如果我执行您的解决方案,一切正常,但是当我尝试对我的函数和表执行相同操作时,我收到以下错误消息:Msg 547, Level 16, State 0, Line 1 ALTER TABLE 语句与 CHECK 约束“CK_MY_CONSTRAINT”冲突。冲突发生在数据库“MY_DB”、表“dbo.MY_TABLE”、列“MY_COLUMN”中。 我不知道为什么,但是我不能改变我的表来添加检查约束而不放置 NOCHECK。 我尝试使用固定值作为参数在外部调用我的函数,我确信我的函数可以按我的意愿工作。 也许当你的 UDF 代码被执行时,它已经看到了你试图插入的同一行(它看到它在表中)。我不知道内部工作原理,现在没有太多时间检查它。但这可能是问题所在。我的 UDF 不会根据同一张表中的某些 SELECT 执行检查,这就是你和我在概念上的不同。 也许这就是问题所在,但我想知道为什么我不能在没有 NOCHECK 扩展的情况下更改我的表并添加检查约束以上是关于为啥这个 Check 约束不起作用?的主要内容,如果未能解决你的问题,请参考以下文章