我非常怀疑这个更新触发器正在更新目标上的所有行,而不仅仅是那些满足“更新(形状)”测试的行。性能很好'直到我添加第二个操作。单个空间连接发生得更快,这不是空间索引问题,此数据集中只有少数记录。
ALTER TRIGGER [dbo].[GRSM_WETLANDS_Point_GIS_tbl_locations_update]
ON [dbo].[GRSM_WETLANDS_POINT]
after update
AS
BEGIN
SET NOCOUNT ON;
if UPDATE (shape)
update GRSM_WETLANDS_Point
set X_Coord =CASE WHEN u.shape.STDimension() = 2 THEN u.shape.STCentroid().STX ELSE u.shape.STEnvelope().STCentroid().STX END,
Y_Coord =CASE WHEN u.shape.STDimension() = 2 THEN u.shape.STCentroid().STY ELSE u.shape.STEnvelope().STCentroid().STY END
from inserted i
inner join GRSM_WETLANDS_POint u on i.GIS_Location_ID = u.GIS_Location_ID;
--second spatial operation
update GRSM_WETLANDS_Point
set QuadName = grsm.dbo.USGS_24K_TOPOMAP_BOUNDARIES.name
FROM GRSM_WETLANDS_POint i
inner join grsm.dbo.USGS_24K_TOPOMAP_BOUNDARIES
on i.GIS_Location_ID = i.GIS_Location_ID
WHERE (USGS_24K_TOPOMAP_BOUNDARIES.Shape.STContains(i.SHAPE) = 1) ;
end
我的怀疑是对的吗?
Upated:根据Aaron的建议......解决所有行问题。
update GRSM_WETLANDS_Point
set QuadName = grsm.dbo.USGS_24K_TOPOMAP_BOUNDARIES.name
FROM inserted i inner join GRSM_WETLANDS_POint u on i.GIS_Location_ID = u.GIS_Location_ID
left outer join grsm.dbo.USGS_24K_TOPOMAP_BOUNDARIES
on i.GIS_Location_ID = i.GIS_Location_ID
WHERE (USGS_24K_TOPOMAP_BOUNDARIES.Shape.STContains(i.SHAPE) = 1);
答案 0 :(得分:3)
如果Shape
不能为NULL,则查看其是否已更改的更好方法是检查inserted
和deleted
中的值是否不同。例如:
IF EXISTS
(
SELECT 1 FROM inserted AS i
INNER JOIN deleted AS d
ON i.GIS_Location_ID = d.GIS_Location_ID
WHERE i.Shape.STEquals(d.Shape) = 0
)
BEGIN
...
END
如果Shape
可以为空,那么您只需在那里添加更多条件进行检查,例如
WHERE
(
(i.Shape IS NULL AND d.Shape IS NOT NULL
OR (i.Shape IS NOT NULL AND d.Shape IS NULL)
OR (i.Shape.STEquals(d.Shape) = 0)
)
(您可能不在乎Shape
是否已更新到 NULL
,我只是说明如何测试该案例。)
由于操作可能发生在多个行上,并且此条件只会识别至少发生过一次此类更新(但并非所有行都符合条件),因此最好让您的操作包含类似的条件。 WHERE子句。事实上,我认为您可以在一次操作中执行这两种更新,例如
ALTER TRIGGER [dbo].[GRSM_WETLANDS_Point_GIS_tbl_locations_update]
ON [dbo].[GRSM_WETLANDS_POINT]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE p SET
X_Coord = CASE WHEN i.shape.STDimension() = 2
THEN i.shape.STCentroid().STX
ELSE i.shape.STEnvelope().STCentroid().STX
END,
Y_Coord = CASE WHEN i.shape.STDimension() = 2
THEN i.shape.STCentroid().STY
ELSE i.shape.STEnvelope().STCentroid().STY
END,
QuadName = COALESCE(b.name, p.QuadName)
FROM
dbo.GRSM_WETLANDS_Point AS p
INNER JOIN
inserted AS i
ON i.GIS_Location_ID = p.GIS_Location_ID
LEFT OUTER JOIN grsm.dbo.USGS_24K_TOPOMAP_BOUNDARIES AS b
ON b.Shape.STContains(i.Shape) = 1
WHERE EXISTS
(
SELECT 1 FROM inserted AS i2
INNER JOIN deleted AS d
ON i2.GIS_Location_ID = d.GIS_Location_ID
WHERE i2.GIS_Location_ID = i.GIS_Location_ID
AND i2.Shape.STEquals(d.Shape) = 0
-- ...and NULL handling if necessary
);
END
GO
一般来说,你似乎在实现触发器方面遇到了很多麻烦,并且对语法应该如何工作做了很多猜测。您是否考虑过通过存储过程强制进行数据更新,您可以在其中控制所有这些业务逻辑,但消除了inserted
和deleted
伪表添加的复杂性?
答案 1 :(得分:2)
如果UPDATE(形状)即使值没有改变也会触发,如果更新语句中存在该列,它将触发
您未在第二次更新中加入INSERTED