【问题标题】:SQL geometry::STGeomFromText throwing error and stopping jobSQL geometry::STGeomFromText 抛出错误并停止作业
【发布时间】:2017-06-20 10:49:19
【问题描述】:

伙计们,

有一个奇怪的给你。

我有一个存储过程,用于解析一些表格数据以创建适当的 SQL 几何对象。

SP 使用函数 MakeValid()。

就我而言,我发现了一些未通过测试的对象。但是,这些不会破坏存储过程。存储过程很高兴运行,并在结果中简单地显示错误。

消息 6522,级别 16,状态 1,行 257 发生 .NET Framework 错误 在执行用户定义的例程或聚合“几何”期间: System.FormatException:24306:

但是,当我在计划的作业中执行此 SP 时,它第一次遇到这些异常之一时,作业失败并且 SP 停止运行。

我实际上不确定在这里做什么。我尝试了一个 TRY..CATCH 块,但这并不能阻止引发的错误,并且作业仍然退出。

因此,虽然它是一个引发错误的 MakeValid 函数,但我想一个遇到函数错误的 SP 会导致同样的问题。

任何想法我可以如何处理这个?顺便说一句,除了标记错误然后返回并修复它们之外,我无法控制输入质量。不过,我仍然希望处理其余的有效记录。

这是可操作的代码部分。

SET @GEOM = geometry::STGeomFromText(@GEOMWKT, 4326)

IF @GEOM.STIsValid() = 0
BEGIN
    BEGIN TRY
        SET @GEOM = @GEOM.MakeValid()
    END TRY
    BEGIN CATCH
        Print 'Error here'
    END CATCH
END 

这是一个引发错误的无效几何的示例。

SET @GEOM = geometry::STGeomFromText('LINESTRING(-121.895652 37.37225, -121.895652 37.37225)', 4326)

感谢您的所有帮助。

【问题讨论】:

  • 您正在检查@GEOM,但对@VALGEOM 执行操作。这是你的意图吗?
  • 坚果。那将是最简单的解决方案。你能提供一个产生这个错误的简单 WKT 吗?
  • 这里是一个引发错误的语法示例。 SET @GEOM = geometry::STGeomFromText('LINESTRING(-121.895652 37.37225, -121.895652 37.37225)', 4326) 也添加到原始问题中。
  • 那条线的两个端点是同一个点。因此,我认为它不是有效的 WKT。也就是说,无法使它有效。你的期望是什么?那个 MakeValid 返回一个 NULL 值?
  • 在其他新闻中,我的笔记本电脑上有一个 SQL 2014 实例,您指定的几何实例和调用 MakeValid() 都对我有用。所以这可能只是“空间是 2008 年的 v1;警告购买者”的情况。

标签: sql sql-server stored-procedures sql-server-2008-r2


【解决方案1】:

我很难验证这是否适合您(即我的本地实例在调用MakeValid()太好),但这可能只适合您。

using Microsoft.SqlServer.Server;
using Microsoft.SqlServer.Types;
using System.Data.SqlTypes;

public partial class UserDefinedFunctions
{
    [SqlFunction]
    public static SqlGeometry TryMakeValid_geometry(SqlGeometry g)
    {
        SqlGeometry r;
        try
        {
            r = g.MakeValid();

        }
        catch (System.Exception)
        {
            r = SqlGeometry.Null;
        }
        return r;
    }

    [SqlFunction]
    public static SqlGeometry TryParseWKT_geometry(SqlString wkt)
    {
        SqlGeometry r;
        try
        {
            r = SqlGeometry.Parse(wkt).MakeValid();
        }
        catch
        {
            r = SqlGeometry.Null;
        }
        return r;
    }
}

将此 CLR 部署到您的数据库并使用您的几何实例调用该函数。如果对 MakeValid() 的调用失败,它应该返回 NULL。

【讨论】:

  • Ben 我编译并部署了这个。给跟随的任何人的小提示 在 Visual Studio 中,您需要为 SQL 2008 编译 .Net 2.0。更高版本的 .Net 支持更高版本的 SQL。结果,我似乎完全错误地描述了这个问题。错误是由 SET @GEOM = geometry::STGeomFromText( 而不是 MakeValid() 行引发的。所以就像我读过的许多其他线程一样,我实际上并没有在构建代码的过程中发现错误。我将重新编写代码,看看是否只需正确编写它就可以解决问题!
  • 是什么东西扔的?!我如坐针毡!
  • 由 SET @GEOM = geometry::STGeomFromText(@GEOMWKT, 4326) 行抛出。如果您将此行传递给无效的几何图形,则会引发错误。但是请参阅我的下一条评论。
  • 好的,这令人沮丧。在此页面上msdn.microsoft.com/en-us/library/bb933890.aspx 这是备注部分中的引用“SQL Server 仅生成有效的几何实例,但允许存储和检索无效实例。表示相同点集的有效实例可以使用 MakeValid() 方法检索任何无效实例。”但是,这似乎在 SQL 2012 上受支持。正如您在 2008 年建议的那样,我可能是 SOL。
  • 啊!我理解你的沮丧。我编辑了上面的代码以添加另一个尝试解析的 CLR UDF。如果解析或对MakeValid() 的调用失败,它会返回一个NULL 值但不会出错。这个我可以测试;我将KITTEN 作为我的WKT 传递,它确实返回了一个NULL 值(而将它传递给STGeomFromText() 确实会引发CLR 错误)。
【解决方案2】:

好的,这就是我要使用的答案,但重要的功劳归功于 Ben Thul 的 CLR,它使用不同的方法实现了相同的结果。

实现是更正确地理解问题。我犯了两个错误。第一个是没有意识到我试图捕捉的错误在 TRY..CATCH 块之外。第二个是相信我需要尝试验证几何的 WKB 表达式。事实上,以下方法允许在尝试创建 WKB 之前验证 WKT。以下方法识别无效的 WKT,设置 TRUE/FALSE 条件。通过 WKT 验证,可以安全地创建有效的 WKB。

一旦我理解了提出正确问题的问题,就会在这里找到解决方案。 https://gis.stackexchange.com/questions/66642/detecting-invalid-wkt-in-text-column-in-sql-server

我已经修改了代码以适应我的实现。

/*REVISED CODE*/

DECLARE @valid bit
DECLARE @GEOMWKT varchar(max)
DECLARE @GEOM geometry

Set @GEOMWKT = 'LINESTRING(-121.895652 37.37225, -121.895652 37.37225)'-- Test faulty value
Set @valid = 1
--Test WKT
BEGIN TRY                                                           --The is the test here. 
    SET @valid = geometry::STGeomFromText(@GEOMWKT, 4326).STIsValid()--We don't try to 
 END TRY                                                            --MakeValid(). No point.
BEGIN CATCH
    SET @valid = 0
END CATCH
--Now that we know whether the WKT will pass or fail we can operate in a known 
--state and avoid raising an error
IF @valid = 1
BEGIN
    SET @GEOM = geometry::STGeomFromText(@GEOMWKT, 4326)--Safely create a valid WKB
END 
ELSE
BEGIN
   SET @GEOM = geometry::STGeomFromText('POINT EMPTY', 4326)-- Set geometry to empty on fail
   Print 'Geometry Fail'
END 

【讨论】:

  • 对您的问题非常有用的解决方案 - 我很容易适应自己的问题。谢谢!
猜你喜欢
  • 2021-03-19
  • 2020-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 2020-10-04
  • 2021-11-21
  • 1970-01-01
相关资源
最近更新 更多