我知道我会因此而受到抨击,但是......
我有表ProductA,ProductB和ProductC,它们具有非常相似的模式,但每个表中有2或3列。每个表都有一个插入触发器,它会将A,B或C中每个插入的重复行触发到表产品,这是所有产品的合并。此外,A,B或C上的更新触发器同样会更新表产品中的等效行,删除触发器也是如此。所有工作都完美无缺,直到.....我们更新表产品A列,表A,B和C中也存在。
我正在寻求在Table Products上开发一个触发器,它将在表A,B和C,BUT中的每一个中将A列中的更新传播到A列,而不调用表A,B和表A上的更新触发器C.所需的行为是更新在两个方向上工作而不会产生无限循环。(注意,表产品中只有2列需要复制到表A,B和C)
选项包括:
从概念上讲,如何做到这一点?
6/7更新:
这是表A中的触发代码(例如):
ALTER TRIGGER [dbo].[GRSM_WETLANDS_Point_GIS_tbl_locations_update]
ON [dbo].[GRSM_WETLANDS_POINT]
after update
AS
BEGIN
SET NOCOUNT ON;
update dbo.TBL_LOCATIONS
set
X_Coord = i.X_Coord,
Y_Coord = i.Y_Coord,
PlaceName = i.PlaceName,
FCSubtype = case
when i.FCSubtype = 1 then 'Point: Too Small to Determin Boundary'
when i.FCSubtype = 2 then 'Point: Boundary Determined by Contractor but not Surveyed'
when i.FCSubtype = 3 then 'Point: Wetland Reported but not yet Surveyed'
end ,
Landform = i.Landform
from dbo.TBL_LOCATIONS
Join inserted i
on TBL_LOCATIONS.GIS_Location_ID = i.GIS_Location_ID
end
GO
并且
ALTER TRIGGER [dbo].[GRSM_WETLANDS_POINT_GIS_tbl_locations]
ON
[dbo].[GRSM_WETLANDS_POINT]
after INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.TBL_LOCATIONS(
X_Coord, Y_Coord,
PlaceName,
FCSubtype, Landform
)
SELECT
a.X_Coord, a.Y_Coord,
a.PlaceName,
a.FCSubtype, a.Landform
From
(
SELECT
X_Coord, Y_Coord,
PlaceName,
FCSubtype = case
when FCSubtype = 1 then 'Point: Too Small to Determin Boundary'
when FCSubtype = 2 then 'Point: Boundary Determined by Contractor but not Surveyed'
when FCSubtype = 3 then 'Point: Wetland Reported but not yet Surveyed'
end ,
Landform
FROM inserted
) AS a
end
GO
以下是表产品上当前禁用的更新触发器:
ALTER TRIGGER [dbo].[tbl_locations_updateto_geo]
ON [dbo].[TBL_LOCATIONS]
for update
AS
BEGIN
--IF @@NESTLEVEL>1 RETURN
SET NOCOUNT ON;
update dbo.GRSM_Wetlands_Point
set
X_Coord = i.X_Coord,
Y_Coord = i.Y_Coord,
PlaceName = i.PlaceName,
FCSubtype = i.FCSubtype,
Landform = i.Landform,
from dbo.TBL_LOCATIONS
Join inserted i
on TBL_LOCATIONS.GIS_Location_ID = i.GIS_Location_ID
where TBL_LOCATIONS.FCSubtype = 'Polygon: Determination Made by GPS Survey'
or TBL_LOCATIONS.FCSubtype = 'Polygon: Determination Derived from NWI'
or TBL_LOCATIONS.FCSubtype = 'Polygon: Determination Made by Other Means'
or TBL_LOCATIONS.FCSubtype = 'Polygon: Legal Jurisdictional Determination';
end
GO
(更改了tbl名称以与发布文本保持一致)
答案 0 :(得分:5)
有两种类型的递归,直接和间接:http://msdn.microsoft.com/en-us/library/ms190739.aspx
您可以使用RECURSIVE_TRIGGERS选项来停止直接递归,但您的情况是间接递归,因此您必须设置嵌套触发器选项。这将解决您的问题,但如果系统中的任何其他内容依赖于递归,那么它将不是一个好的选择。
USE DatabaseName
GO
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
EXEC sp_configure 'nested triggers', 0
GO
RECONFIGURE
GO
编辑以回复您的更新帖子:
我几乎不愿意给你这个解决方案,因为你最终采取了一个非常糟糕的设计并扩展它......使它变得比现在更糟糕,而不是花时间去了解发生了什么,只是修复它。你应该诚实地创建另一个表来保存两个表之间需要同步的值,这样数据只在一个地方,然后通过一个键将这些表与那个表相关联。但尽管如此......
你需要一个标志来设置你在一个触发器中更新,这样另一个触发器可以在它看到它是真的时中止它的操作。因为(据我所知)你只能拥有本地范围的变量,这意味着你需要一个表来存储这个标志值并从中查找。
您可以使用不同级别的复杂性来实现此解决方案,但最简单的方法是让所有触发器在启动时将标志设置为true,在结束时将标志设置为false。在他们开始之前,他们检查标志并停止执行,如果它是真的;
这个问题是可能存在另一个与同时发生的触发无关的更新,它不会传播到下一个表。如果你想采取这条路线,那么我将由你决定如何解决这个问题。