确定哪些行导致查询错误
Determine what rows are causing error in query
我有一个 Oracle 18c table,它有 15,000 行。作为测试,我正在尝试 运行 以下查询:
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() 来查找问题 blob。但是,令人惊讶的是,它没有 return 任何 FALSE
值。
尝试循环执行(row-by-row,这将是 slow-by-slow,但是 - 如果您没有更好的东西,请耐心等待 - 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;
/
创建一个函数来包装导致问题的调用并捕获函数中的异常:
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;
使用@MTO 和@LittleFoot 提供的解决方案,我能够确定以下内容:
问题似乎发生在 WKB 几何体为 3d — 和 — multi-part 时。 to_wkbgeometry()
函数无法将 3d multi-part WKB 转换为 SDO_GEOMETRY。我认为这可能是 Oracle 错误。
这里有更多信息:Convert 3d multi-part WKB to SDO_GEOMETRY
测试:
作品: 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
作品: 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
无效: 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
错误:
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.
我有一个 Oracle 18c table,它有 15,000 行。作为测试,我正在尝试 运行 以下查询:
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() 来查找问题 blob。但是,令人惊讶的是,它没有 return 任何 FALSE
值。
尝试循环执行(row-by-row,这将是 slow-by-slow,但是 - 如果您没有更好的东西,请耐心等待 - 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;
/
创建一个函数来包装导致问题的调用并捕获函数中的异常:
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;
使用@MTO 和@LittleFoot 提供的解决方案,我能够确定以下内容:
问题似乎发生在 WKB 几何体为 3d — 和 — multi-part 时。 to_wkbgeometry()
函数无法将 3d multi-part WKB 转换为 SDO_GEOMETRY。我认为这可能是 Oracle 错误。
这里有更多信息:Convert 3d multi-part WKB to SDO_GEOMETRY
测试:
作品: 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
作品: 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
无效: 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
错误:
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.