触发器递归更新 树形结构子节点

来源:互联网 发布:虐杀原形2a卡优化 编辑:程序博客网 时间:2024/05/17 20:15

部门信息 树形结构如下 

CREATE TABLE [dbo].[Business_Department]([DepartmentID] [nvarchar](100) COLLATE Chinese_PRC_CI_AS NOT NULL,[DepartmentName] [nvarchar](100) COLLATE Chinese_PRC_CI_AS NOT NULL,[ParentID] [nvarchar](100) COLLATE Chinese_PRC_CI_AS NULL CONSTRAINT [DF_Business_Department_ParentID]  DEFAULT (N'root'),[DepartmentLevel] [int] NOT NULL CONSTRAINT [DF_Table_1_MenuLevel]  DEFAULT ((1)),[DepartmentPath] [nvarchar](2000) COLLATE Chinese_PRC_CI_AS NULL,  CONSTRAINT [PK_Business_Department] PRIMARY KEY CLUSTERED ([DepartmentID] ASC)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]) ON [PRIMARY]

使用触发器递归更新子节点


--开启触发器递归ALTER DATABASE xiangjiang   SET RECURSIVE_TRIGGERS ONGOIF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE NAME = 'TR_Department_Update' AND TYPE = 'TR')DROP TRIGGER TR_Department_UpdateGO--创建UPDATE触发器CREATE TRIGGER TR_Department_UpdateON dbo.Business_Department AFTER UPDATE AS--若有记录值变更IF UPDATE(DepartmentID) AND EXISTS(SELECT * FROM INSERTED)BEGIN--变更下级记录自动递归更新UPDATE D set D.DepartmentLevel=I.DepartmentLevel+1, D.DepartmentPath=Replace(D.DepartmentPath,substring(D.DepartmentPath,0,CharIndex(D.ParentID,D.DepartmentPath))+D.ParentID+'/',I.DepartmentPath) FROM dbo.Business_Department  D, INSERTED I WHERE D.ParentID = I.DepartmentIDEND 


如有另外的触发器又不允许递归可用一下方法针对具体触发器处理

1.       使用update(列名)函数
此函数适用于对 UPDATE 的控制。对于"A表UPDATE 后,取B表某列再次UPDATE A表",如果仅更新A表的某些列才触发UPDATE B, 并且B 表再次UPDATE A表不会包含A表触发UPDATE B的那些列,则在A表的触发器中,使用IF UPDATE(列)来确定是否应该UPDATE B即可。
2.       使用@@NESTLEVEL
该变量值确定嵌套层数。
对于"A表update后,取B表某列再次UPDATE A表",如果触发者不是一个存储过程, 则UPDATE A 的A表触发器@@NESTLEVEL = 1, 到UPDATE B时, B表触发器 @@NESTLEVEL = 2, B表触发器再UPDATE A时, @@NESTLEVEL = 3。
所以如果 @@NESTLEVEL >=3 时, 一般表示递归了(当然, 前提是UPDATE A的触发器本身没有两层的递归, 即不能是存储过程再调用存储过程去UPDATE A。
3.       使用 @@PROCID
该全局变量返回调用者的object_id。如果需要A表触发B表触发器,而B表触发器再触发A表触发器时,A表触发器不响应;则在A表触发器中使用它来判断触发者是谁,如果是B表触发器,则不处理就行了,类似下面这样:
IF OBJECT_ID(N'B表触发器名称') = @@PROCID
BEGIN
    PRINT 'B表触发器, 不处理'
    RETURN
END