Count Distinct在SQL Server 2008中的UDF中不起作用

时间:2015-10-05 17:01:21

标签: sql-server-2008 tsql user-defined-functions

我在查询中使用count distinct创建UDF时遇到问题。我创建了一个表 amtest ,其中包含以下内容:

CREATE TABLE [dbo].[amtest](
    [ztime] [datetime] NULL,
    [zutime] [datetime] NULL,
    [zid] [int] NOT NULL,
    [xamacadyr] [int] NOT NULL,
    [xamreg] [varchar](20) NOT NULL,
    [xmobile] [varchar](15) NULL,
    [xamclasssec] [varchar](30) NULL,
PRIMARY KEY CLUSTERED 
(
    [zid] ASC,
    [xamacadyr] ASC,
    [xamreg] ASC
)

amtest 表格中的数据如下:

zid xamacadyr   xamreg      xmobile         xamclasssec
100000  2013        201508001   01713236075     Section-B
100000  2014        201508003   01713236072     Section-A
100000  2015        201508001   01713236071     Section-A
100000  2015        201508003   01713236073     Section-A
100000  2015        201508004   01713236074     Section-A

现在我创建了一个带参数xamreg的用户定义函数,这样,对于任何xamreg值,xamclasssec字段中都不能有2个不同的值。例如,对于xamreg中的 201508001 值,不应该有2个不同的值(Section-A,Section-B),它应该只允许 Section-A 栏目-B 即可。为此,我创建了以下UDF:

ALTER FUNCTION [dbo].[CheckTest](@xamreg varchar(30))
RETURNS int
AS
BEGIN
    DECLARE @retvar int;
    select @retvar = COUNT(*) from (select xamclasssec from amtest where xamreg=@xamreg group by xamclasssec) as tbl ;
    RETURN @retvar
END

我已经为amtest表创建了一个约束,如下所示:

alter table amtest  
add constraint chkAmtest  
check(dbo.CheckTest(xamreg)<=1)  

我犯了错误,因为它不起作用?

2 个答案:

答案 0 :(得分:0)

首先,您的功能可以简化为:

CREATE FUNCTION [dbo].[CheckTest](@xamreg varchar(30))
RETURNS INT
AS
BEGIN
    RETURN (SELECT COUNT(DISTINCT xamclasssec) FROM amtest WHERE xamreg = @xamreg);
END
GO

我使用SQL Fiddle运行您的查询它似乎可以工作,但仅适用于INSERT

<强> SqlFiddleDemo

如果我尝试设置DISTINCT值:

  

INSERT语句与CHECK约束“chkAmtest”冲突。   冲突发生在数据库“db_3_5ec42”,表“dbo.amtest”中,   列'xamreg'。

但是您的解决方案有一个缺点,它会在UPDATE发生时无效。

<强> SqlFiddleDemo2

INSERT INTO [dbo].[amtest]
        (zid ,xamacadyr  , xamreg ,     xmobile  ,       xamclasssec)
VALUES (100000 , 2013  ,      201508001 ,  01713236075 ,    'Section-B'),
       (100000,  2015,        201508001 ,  01713236071 ,    'Section-B');

UPDATE [dbo].[amtest]
SET xamclasssec =  'Section-A'
WHERE xmobile = 01713236071;

SELECT *
FROM [dbo].[amtest];

改为使用 AFTER TRIGGER

<强> SqlFiddleDemo3

CREATE TRIGGER trg_amtest 
ON [dbo].[amtest]
AFTER INSERT, UPDATE
AS
  IF EXISTS (SELECT xamreg, COUNT(DISTINCT xamclasssec)
             FROM amtest
             GROUP BY xamreg
             HAVING COUNT(DISTINCT xamclasssec) > 1)
  ROLLBACK;
GO

答案 1 :(得分:0)

如果我错了,请告诉我,但是这个UDF会返回2。 这是你想要的吗?