使用mssql层次结构检查constrint时如何摆脱超时错误

时间:2016-12-02 14:37:18

标签: sql-server tsql

我正在创建sql hirercky表

这是我的代码;

约束功能代码

                    alter Function Accounts.Types_Sub_Check_fn (@ID uniqueidentifier, @Sub Uniqueidentifier) returns int
                    begin
                    --declare @id uniqueidentifier = '8c7d4151-246c-476c-adf6-964ca9afdd3c' declare @sub uniqueidentifier = '47c2b6da-25fc-4921-adfa-b1f635bddde6'
                    declare @a int
                    declare @b int =(iif(@ID=@SUB,2,0))

                    ;with cte(id, lvl) as
                      (
                        select f.sub,
                               1
                        from Accounts.Types as f
                        where f.id = @id
                        union all
                        select f.sub,
                               lvl + 1
                        from Accounts.Types as f
                          inner join cte as c
                            on f.id = c.id
                      )
                      select @a = (select count (*)
                                     from cte
                                     where id =@sub) + @b


                      option (maxrecursion 0)


                        return @a
                    end
                    go

表格代码

   create Table Accounts.Types
                        (
                        ID uniqueidentifier  not null CONSTRAINT DF_Accounts_Types_ID DEFAULT newid() CONSTRAINT PK_Accounts_Types_ID PRIMARY KEY NONCLUSTERED (ID) ,
                        Name varchar(200) not null CONSTRAINT UQ_Accounts_Types_NAME UNIQUE (NAME), 
                        Sub uniqueidentifier CONSTRAINT FK_Accounts_Types_Sub Foreign key references Accounts.Types ,
                        Ctype uniqueidentifier CONSTRAINT FK_Accounts_Types_Ctype Foreign key references Accounts.Types ,
                        insert_time datetime not null CONSTRAINT DF_Accounts_Types_Insert_Time DEFAULT getdate() ,
                        insert_user uniqueidentifier CONSTRAINT DF_Accounts_Types_Insert_User DEFAULT'9EC66F53-9233-4A6C-8933-F8417D2BB5A9'  ,
                        ts timestamp,
                        INDEX IX_Accounts_Types_NAME#ASC CLUSTERED (Name ASC),
                        Constraint Check_Accounts_Types_Sub check (Accounts.Types_Sub_Check_fn(ID,Sub)<=1)
                        )
                        go

如果尝试将itseft作为父项(在子列中)

插入,则此函数将给出2

如果它已经是一个孩子,它会给1,它试图作为其父

插入

创建Check约束以检查任何id的父(子列)是否不应该是其子或子, 并且它本身不能是它的父母

当我尝试插入与检查约束不匹配的数据时,它会卡住,并发出超时错误,

例如:

   insert into Accounts.Types (ID, Name, Sub)
   values ('607936b9-6f95-4989-8ebe-87a08807f43e','LLL','607936b9-6f95-4989-8ebe-87a08807f43e')

这会给出超时

任何人都可以帮助我,我需要摆脱时间错误;仅获取约束错误

2 个答案:

答案 0 :(得分:1)

简单的问题 - 当您的ID和Sub是相同的值并且您不限制maxrecursion或lvl时,您的递归何时结束?决不。它永远不会结束。

if (($date >= $snowStart) && ($date <= $snowEnd)) 
{
     // do this and that
}

您必须删除ID = Sub的行或添加maxrecursion或添加级别限制或规范化表格。

答案 1 :(得分:0)

            alter Function Accounts.Types_Sub_Check_fn (@ID uniqueidentifier, @Sub Uniqueidentifier) returns int
                    begin
                    --declare @id uniqueidentifier = '00279c6b-df00-4144-810d-571fdb1c5109' declare @sub uniqueidentifier = 'bc887e7b-36d2-4ece-8ec1-720dc81a9de4'
                    declare @a int = 0
                    declare @b int =(iif(@ID=@SUB,2,0))
                    if @ID <> @sub
                    begin
                    ;with cte(id, lvl) as
                      (
                        select f.Sub ,
                               1
                        from Accounts.Types as f
                        where f.id = @sub 
                        union all
                        select  iif(f.Sub = @sub, Null, f.sub),
                               lvl + 1
                        from Accounts.Types as f
                          inner join cte as c
                            on f.id = c.id 
                      )

                      select @a = (select count (*)
                                     from cte
                                     where id =@id) 

        option (maxrecursion 0);


                      end
                    --  select @a + @b


                        return @a + @b
                    end
                    go