确定哪些行在查询中导致错误

发布于 2025-02-03 20:07:08 字数 1501 浏览 2 评论 0原文

我有一个有15,000行的Oracle 18C表。作为测试,我正在尝试在其中运行以下查询:

select
    --works for all rows:
    --sdo_util.to_wkbgeometry(sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING')))
    
    --doesn't work for all rows (the problem is caused by: SDO_UTIL.FROM_WKBGEOMETRY() ):
    sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))))
from
    my_table;

当我在SQL Developer中运行该查询时,它最初是没有错误的,但这仅仅是因为它仅选择前50行。

如果我尝试在所有行上运行查询(通过CTRL+END),那么它会引发一个错误:

ORA-29532: Java call terminated by uncaught Java exception: java.lang.RuntimeException: oracle.spatial.util.GeometryExceptionWithContext: Byte order can only be either BIG_ENDIAN (encoded as 0) or LITTLE_ENDIAN (encoded as 1). Found encoding 65
ORA-06512: at "MDSYS.SDO_JAVA_STP", line 68
ORA-06512: at "MDSYS.SDO_UTIL", line 6244
29532. 00000 -  "Java call terminated by uncaught Java exception: %s"
*Cause:    A Java exception or error was signaled and could not be
           resolved by the Java code.
*Action:   Modify Java code, if this behavior is not intended.

如何确定哪些特定行引起该错误?

我尝试使用 sdo_util.validate_wkbgeometry()找到问题斑点。但是,令人惊讶的是,它没有返回任何false值。

I have an Oracle 18c table that has 15,000 rows. As a test, I'm trying to run the following query on it:

select
    --works for all rows:
    --sdo_util.to_wkbgeometry(sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING')))
    
    --doesn't work for all rows (the problem is caused by: SDO_UTIL.FROM_WKBGEOMETRY() ):
    sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))))
from
    my_table;

When I run that query in SQL Developer, it initially runs without errors, but that's just because it's only selecting the first 50 rows.

If I try to run the query on all rows (via CTRL+END), then it throws an error:

ORA-29532: Java call terminated by uncaught Java exception: java.lang.RuntimeException: oracle.spatial.util.GeometryExceptionWithContext: Byte order can only be either BIG_ENDIAN (encoded as 0) or LITTLE_ENDIAN (encoded as 1). Found encoding 65
ORA-06512: at "MDSYS.SDO_JAVA_STP", line 68
ORA-06512: at "MDSYS.SDO_UTIL", line 6244
29532. 00000 -  "Java call terminated by uncaught Java exception: %s"
*Cause:    A Java exception or error was signaled and could not be
           resolved by the Java code.
*Action:   Modify Java code, if this behavior is not intended.

How can I determine what specific rows are causing that error?

I tried using SDO_UTIL.VALIDATE_WKBGEOMETRY() to find the problem blobs. But, surprisingly, it didn't return any FALSE values.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

又爬满兰若 2025-02-10 20:07:08

创建一个函数来包装引起问题的调用并在函数中捕获异常:

CREATE FUNCTION test_from_wkbgeometry(
  v_data IN BLOB
) RETURN NUMBER
IS
  temp SDO_GEOMETRY;
BEGIN
  temp := sdo_util.from_wkbgeometry(v_data);
  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
    RETURN 0;
END;
/

然后在查询中使用它:

SELECT *
FROM   my_table
WHERE  test_from_wkbgeometry(
         sdo_util.to_wkbgeometry(
           sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))
         )
       ) = 0;

在以后的Oracle版本中,您可以在查询中定义函数:

WITH FUNCTION test_from_wkbgeometry(
  v_data IN BLOB
) RETURN NUMBER
IS
  temp SDO_GEOMETRY;
BEGIN
  temp := sdo_util.from_wkbgeometry(v_data);
  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
    RETURN 0;
END;
SELECT *
FROM   my_table
WHERE  test_from_wkbgeometry(
         sdo_util.to_wkbgeometry(
           sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))
         )
       ) = 0;

Create a function to wrap the call that is causing issues and catch the exception in the function:

CREATE FUNCTION test_from_wkbgeometry(
  v_data IN BLOB
) RETURN NUMBER
IS
  temp SDO_GEOMETRY;
BEGIN
  temp := sdo_util.from_wkbgeometry(v_data);
  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
    RETURN 0;
END;
/

Then use it in your query:

SELECT *
FROM   my_table
WHERE  test_from_wkbgeometry(
         sdo_util.to_wkbgeometry(
           sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))
         )
       ) = 0;

In later Oracle versions, you can define the function in the query:

WITH FUNCTION test_from_wkbgeometry(
  v_data IN BLOB
) RETURN NUMBER
IS
  temp SDO_GEOMETRY;
BEGIN
  temp := sdo_util.from_wkbgeometry(v_data);
  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
    RETURN 0;
END;
SELECT *
FROM   my_table
WHERE  test_from_wkbgeometry(
         sdo_util.to_wkbgeometry(
           sdo_geometry(replace(sde.st_astext(shape),'LINESTRING M','LINESTRING'))
         )
       ) = 0;
黎歌 2025-02-10 20:07:08

尝试在循环中进行操作(逐行会很慢,但是 - 如果您没有更好的耐心,请耐心等待-15.000行不会那么多...)。在代码中读取评论。

declare
  l_geom sdo_geometry;  --> I'm not sure what datatype is result of all those
                        --  geometry functions' call; I guess it is SDO_GEOMETRY.
                        --  If not, use appropriate datatype.
begin
  for cur_r in 
    (select
       id,     --> I guess there must be some kind of an ID; if not, pick any other 
               --  column which will uniquely identify that particular row
       shape
     from my_table
    ) 
  loop
    -- inner BEGIN-EXCEPTION-END block which will "capture" error on that row,
    -- but will also let the loop continue until the last row fetched by the cursor
    begin
      l_geom := sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry(replace(sde.st_astext(cur_r.shape),'LINESTRING M','LINESTRING'))));
    exception
      when others then
        dbms_output.put_line('Error on ID = ' || cur_r.id ||': '|| sqlerrm);
    end;
  end loop;
end;
/

Try to do it in a loop (row-by-row which will be slow-by-slow, but - if you don't have anything better, be patient - 15.000 rows isn't that much ...). Read comments within code.

declare
  l_geom sdo_geometry;  --> I'm not sure what datatype is result of all those
                        --  geometry functions' call; I guess it is SDO_GEOMETRY.
                        --  If not, use appropriate datatype.
begin
  for cur_r in 
    (select
       id,     --> I guess there must be some kind of an ID; if not, pick any other 
               --  column which will uniquely identify that particular row
       shape
     from my_table
    ) 
  loop
    -- inner BEGIN-EXCEPTION-END block which will "capture" error on that row,
    -- but will also let the loop continue until the last row fetched by the cursor
    begin
      l_geom := sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry(replace(sde.st_astext(cur_r.shape),'LINESTRING M','LINESTRING'))));
    exception
      when others then
        dbms_output.put_line('Error on ID = ' || cur_r.id ||': '|| sqlerrm);
    end;
  end loop;
end;
/
迷爱 2025-02-10 20:07:08

使用@MTO和@LittleFoot提供的解决方案,我能够确定以下内容:

当WKB几何形状为 3D和 - 多部分时,问题似乎会发生。 to_wkbgeometry()函数无法将3D多部分WKB转换为SDO_GEOMETRY。我认为这可能是一个甲骨文错误。

更多信息在这里:将3D多部分WKB转换为SDO_GEOMETRY


测试:

作品: 3D,单部分:

select
  --Works: 3d, single-part
  sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry('LINESTRING (1 2 3, 4 5 6)')))
from
  dual

工作: 2D,多部分:

select
  --Works: 2d, multi-part
  sdo_util.to_wkbgeometry(sdo_geometry('MULTILINESTRING ((1 2, 4 5),(7 8, 0 1))'))
from
  dual

't工作: 3D,多部分:

select
  --Doesn't work: 3d, multi-part
  sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry('MULTILINESTRING ((1 2 3, 4 5 6),(7 8 9, 0 1 3))')))
from
  dual 

错误:

ORA-29532: Java call terminated by uncaught Java exception: java.lang.RuntimeException: oracle.spatial.util.GeometryExceptionWithContext: Byte order can only be either BIG_ENDIAN (encoded as 0) or LITTLE_ENDIAN (encoded as 1). Found encoding 64
ORA-06512: at "MDSYS.SDO_JAVA_STP", line 68
ORA-06512: at "MDSYS.SDO_UTIL", line 6244
29532. 00000 - "Java call terminated by uncaught Java exception: %s"
*Cause:  A Java exception or error was signaled and could not be
      resolved by the Java code.
*Action:  Modify Java code, if this behavior is not intended.

Using the solutions provided by @MTO and @LittleFoot, I was able to determine the following:

The problem seems to happen when a WKB geometry is 3d —and— multi-part. The to_wkbgeometry() function can't convert 3d multi-part WKB to SDO_GEOMETRY. I think that's likely an Oracle bug.

More information here: Convert 3d multi-part WKB to SDO_GEOMETRY


Testing:

Works: 3d, single-part:

select
  --Works: 3d, single-part
  sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry('LINESTRING (1 2 3, 4 5 6)')))
from
  dual

Works: 2d, multi-part:

select
  --Works: 2d, multi-part
  sdo_util.to_wkbgeometry(sdo_geometry('MULTILINESTRING ((1 2, 4 5),(7 8, 0 1))'))
from
  dual

Doesn't work: 3d, multi-part:

select
  --Doesn't work: 3d, multi-part
  sdo_util.from_wkbgeometry(sdo_util.to_wkbgeometry(sdo_geometry('MULTILINESTRING ((1 2 3, 4 5 6),(7 8 9, 0 1 3))')))
from
  dual 

Error:

ORA-29532: Java call terminated by uncaught Java exception: java.lang.RuntimeException: oracle.spatial.util.GeometryExceptionWithContext: Byte order can only be either BIG_ENDIAN (encoded as 0) or LITTLE_ENDIAN (encoded as 1). Found encoding 64
ORA-06512: at "MDSYS.SDO_JAVA_STP", line 68
ORA-06512: at "MDSYS.SDO_UTIL", line 6244
29532. 00000 - "Java call terminated by uncaught Java exception: %s"
*Cause:  A Java exception or error was signaled and could not be
      resolved by the Java code.
*Action:  Modify Java code, if this behavior is not intended.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文