2

この更新トリガーが、「update(shape)」テストを満たす行だけでなく、ターゲットのすべての行を更新しているのではないかと非常に疑わしいと感じています。2 番目の操作を追加するまで、パフォーマンスは良好でした。単一の空間結合ははるかに高速に発生します。これは空間インデックスの問題ではありません。また、このデータセットには少数のレコードしかありません。

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

私の疑いは正しいですか?

更新: 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); 
4

2 に答える 2

3

ShapeNULL にできない場合、変更されたかどうかを確認するより良い方法は、と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

nullable の場合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。その場合のテスト方法を説明しているだけです。)

操作は複数の行で発生する可能性があり、この条件はそのような更新が少なくとも 1 回発生したことのみを識別します (ただし、すべての行が条件を満たしているわけではありません)。操作の WHERE 句に同様の基準を含めることをお勧めします。実際、1回の操作で両方の更新を実行できると思います。

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疑似テーブルによって追加される複雑さを排除できます。

于 2012-06-10T20:17:14.793 に答える
2

値が変更されなくても UPDATE (形状) が起動する場合、更新ステートメントに列が存在する場合は起動します

そして、2回目の更新でINSERTEDに参加していません

于 2012-06-10T19:44:16.057 に答える