SQL Server 2008 R2中获取几何体无效详情的替代方案咨询
在SQL Server 2008 R2中获取几何体无效的详细原因
当然可行!虽然Geometry.IsValidDetailed()是SQL Server 2012才引入的,但我们可以通过几种替代方案来获取几何体无效的具体原因,下面是实用的解决办法:
方法1:利用STMakeValid()对比分析
STMakeValid()在SQL Server 2008 R2中是可用的,它能将无效几何体转换为有效版本。通过对比原始几何体和修复后的结果,我们可以推断出无效的核心原因:
SELECT OriginalGeo = Geo, FixedGeo = Geo.STMakeValid(), -- 判断是否存在自相交(修复后几何体数量变化通常意味着自相交) IsSelfIntersecting = CASE WHEN Geo.STNumGeometries() <> Geo.STMakeValid().STNumGeometries() THEN 1 ELSE 0 END, -- 检查多边形环是否闭合 UnclosedRingIssue = CASE WHEN Geo.STGeometryType() = 'Polygon' AND Geo.STExteriorRing().STIsClosed() = 0 THEN 1 ELSE 0 END FROM GeoTests WHERE Geo.STIsValid() = 0;
方法2:编写自定义函数排查常见无效原因
几何体无效的常见场景包括:重复顶点、未闭合的环、自相交、环方向错误等。我们可以编写一个自定义函数逐一检测这些问题:
CREATE FUNCTION dbo.GetGeometryInvalidReason(@geo geometry) RETURNS nvarchar(500) AS BEGIN DECLARE @reason nvarchar(500) = ''; -- 检查空几何体 IF @geo IS NULL OR @geo.STIsEmpty() = 1 SET @reason = @reason + '空或NULL几何体; '; -- 检查多边形/线是否闭合 IF @geo.STGeometryType() IN ('Polygon', 'LineString') AND @geo.STIsClosed() = 0 SET @reason = @reason + '几何体未闭合; '; -- 检查重复顶点 DECLARE @pointCount int = @geo.STNumPoints(); DECLARE @i int = 1; WHILE @i <= @pointCount BEGIN DECLARE @j int = @i + 1; WHILE @j <= @pointCount BEGIN IF @geo.STPointN(@i).STEquals(@geo.STPointN(@j)) = 1 BEGIN SET @reason = @reason + '位置' + CAST(@i AS nvarchar) + '和' + CAST(@j AS nvarchar) + '存在重复顶点; '; BREAK; END SET @j = @j + 1; END SET @i = @i + 1; END -- 通过缓冲区操作检测自相交 BEGIN TRY DECLARE @buffer geometry = @geo.STBuffer(0); END TRY BEGIN CATCH SET @reason = @reason + '几何体存在自相交; '; END CATCH -- 无具体检测结果时返回通用信息 IF @reason = '' SET @reason = '几何体无效,但未检测到具体原因'; RETURN @reason; END GO -- 使用示例 SELECT Id, Value, dbo.GetGeometryInvalidReason(Geo) AS InvalidReason FROM GeoTests WHERE Geo.STIsValid() = 0;
方法3:优化TRY-CATCH捕获详细错误
你当前的TRY-CATCH代码有语法问题(表名未写完),修正后可以尝试执行一些会触发详细错误的几何体操作,比如STUnion或STIntersection,这些操作在遇到无效几何体时往往会返回更具体的错误描述:
BEGIN TRY SELECT TOP 1000 [Id], [Value], [Geo].STGeometryType(), -- 触发详细错误的操作 [Geo].STUnion([Geo]) AS UnionResult FROM [dbo].[GeoTests] END TRY BEGIN CATCH PRINT '错误信息: ' + ERROR_MESSAGE() PRINT '错误编号: ' + CAST(ERROR_NUMBER() AS nvarchar) END CATCH
比如你插入的那个含重复顶点的无效多边形,执行上述代码会捕获到类似24205: 指定的输入不表示有效的地理实例,因为它包含重复顶点的详细错误。
内容的提问来源于stack exchange,提问作者Kyle B
相关产品推荐
相关产品推荐

