检测有缺陷的几何体WKT并返回有缺陷的记录

时间:2016-02-25 00:48:30

标签: sql sql-server sql-server-2008

民间, 我怀疑这很容易,但我很难找到一个好的参考。

我有一个包含线,点和多边形的WKT列的表。我正在将WKT处理成地理列。

在大部分时间里,我都希望在处理之前对WKT进行质量检查。

我在这里遇到了麻烦。

我尝试过的最简单的事情是

select *  
from GEOMWKT 
where geometry::STGeomFromText(GEOG_WKT, 4326).STIsValid() = 0;

然而,如果记录确实存在错误,则会中断。

A .NET Framework error occurred during execution of user-defined routine or aggregate "geometry": 
System.FormatException: 24117: The LineString input is not valid because it does not have enough distinct points. A LineString must have at least two distinct points.

为了尝试缓解这种情况,我尝试了以下

-- Verify that the stored procedure does not already exist.
IF OBJECT_ID ( 'usp_GetErrorInfo', 'P' ) IS NOT NULL 
    DROP PROCEDURE usp_GetErrorInfo;
GO

-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT
    ERROR_NUMBER() AS ErrorNumber
    ,ERROR_SEVERITY() AS ErrorSeverity
    ,ERROR_STATE() AS ErrorState
    ,ERROR_PROCEDURE() AS ErrorProcedure
    ,ERROR_LINE() AS ErrorLine
    ,ERROR_MESSAGE() AS ErrorMessage;
GO

BEGIN TRY
   select * from GEOMWKT where geometry::STGeomFromText(GEOG_WKT, 4326).STIsValid() = 0;
END TRY
BEGIN CATCH
    -- Execute error retrieval routine.
    EXECUTE usp_GetErrorInfo;
END CATCH; 

虽然这可以恢复它的功能,但是管理并返回了错误,但我仍然不知道它是哪条记录。

如何返回ID列或某些记录失败的内容?

2 个答案:

答案 0 :(得分:0)

创建一个存储过程以将txt转换为几何,也不需要转换为几何,该函数已经返回几何对象。

CREATE PROCEDURE usp_GetGeometry
    (@Geomtxt  varchar(500) )
AS
DECLARE @ReturnValue as geometry

BEGIN TRY
   select @ReturnValue = STGeomFromText(@Geomtxt , 4326);
   RETURN @ReturnValue
END TRY
BEGIN CATCH
     RETURN NULL
END CATCH; 
GO

然后将函数用于每一行。

select *, usp_GetGeometry( GEOG_WKT )
from GEOMWKT

答案 1 :(得分:0)

这是我使用游标的问题的答案。正如我所读,我们不喜欢游标,但这有效。

我更喜欢存储过程或函数的优雅,但这样就完成了。

请注意:根据原始链接,这使用两种方法来查找无效的几何图形。有时你会得到一个重复的ID,有时不依赖于失败。

我仍然对改进感兴趣,因为在我们对它们进行处理之前,我想设置一个存储过程来报告这些内容。

    -- ---------------------------------------------------- 
--   Find invalid geometry in given Spatial table 
-- ---------------------------------------------------- 

DECLARE @id INT, @n INT, @g varchar(max);

-- create error log table
IF EXISTS (SELECT * FROM sys.objects 
  WHERE object_id = OBJECT_ID(N'[dbo].[ERR_CorruptedGeom]') AND type in (N'U'))
DROP TABLE [dbo].[ERR_CorruptedGeom];

CREATE TABLE [dbo].[ERR_CorruptedGeom](
    recordid [int] NULL,
    table_name Varchar(25) NULL,
    errtext Varchar(MAX) NULL
) ON [PRIMARY];

-- define QA cursor on spatial table
DECLARE qa_cursor CURSOR FOR 
    SELECT GEOMID, GEOG_WKT
    FROM dbo.GEOMWKT;

OPEN qa_cursor -- open cursor 
FETCH NEXT FROM qa_cursor INTO @id, @g;

-- run over table records from the begining to the end 
WHILE (@@FETCH_STATUS <> -1) 
BEGIN

BEGIN TRY

  -- conventional way to find invalid geometry 
  IF geometry::STGeomFromText(@g, 4326).STIsValid()=0 
  BEGIN 
    -- insert problematic record number into Log table 
   INSERT INTO dbo.ERR_CorruptedGeom (recordid, table_name, errtext) 
   VALUES (@id, 'dbo.GEOMWKT', 'Invalid Geometry');
  END

  -- trying to read invalid geometry will raise Error 
  SET @n = geometry::STGeomFromText(@g, 4326).STNumGeometries();

END TRY

-- error catch block
BEGIN CATCH

  -- insert problematic record reference to Log table 
  INSERT INTO dbo.ERR_CorruptedGeom (recordid, table_name, errtext)
  VALUES (@id, 'dbo.GEOMWKT', ERROR_MESSAGE());

END CATCH;

FETCH NEXT FROM qa_cursor INTO @id, @g;

END

-- close cursor 
CLOSE qa_cursor;
DEALLOCATE qa_cursor;


-- see results 
select * from ERR_CorruptedGeom

这是来自http://www.sqlexamples.info/SPAT/mssql_invalid_geometry.htm