我们能否找到导致 ORA-00942 table 或视图不存在的 table:
Can we find which table is causing ORA-00942 table or view does not exist.:
我有一个带 CTAS 查询的普通 PLSQL 块。
BEGIN
EXECUTE IMMEDIATE'
CREATE TABLE ZZZ_TEMP NOLOGGING PARALLEL AS
SELECT /*+ PARALLEL(a,4) */
*
FROM
HI0XXX001.HI_TABLE_NAME a
LEFT JOIN
HR_001_GROUP B
ON
a.EMPLOYERGROUP_UD =B.ACC_NUM
LEFT JOIN
HR_002_GROUP l
ON
a.EMPLOYERGROUP_UD =l.EMPLOYERGROUP_UD
AND
a.GRP_CON_UD_COV_CONTRACT_NAME=l.GRP_CON_UD_COV_CONTRACT_NAME
';
EXCEPTION WHEN OTHERS THEN Dbms_Output.put_line(SQLERRM);
END;
让我们假设 HR_002_GROUP table 不存在于我所在的架构中 运行 这个块。有什么方法可以显示 HR_002_GROUP table 不存在的错误消息?
我发布的查询只是一个示例场景。我们在 ETL 结构中工作,我们有一大行查询脚本,将数百万数据从许多 HI table 之一插入到另一个带有前缀 VH 的小 table。我在左连接中有大约 15-30 tables。 select 每个左连接要知道哪个 table 实际上导致错误是很耗时的。
使用DBMS_SQL
代替原生动态SQL,然后使用DBMS_SQL.LAST_ERROR_POSITION()
找出语句中有错误的部分。
DBMS_SQL
不如原生动态 SQL 方便,但也更强大。有几个问题需要注意。第一个是程序 DBMS_SQL.PARSE
不仅解析命令,它还会自动 运行 DDL 命令。
下面的代码尝试使用另外两个 table 创建一个 table,其中一个显然不存在。正则表达式用于输出每个字符
从错误的位置到第一个空格。 (此代码基于this answer.)
declare
v_cursor_id integer := dbms_sql.open_cursor ();
v_sql varchar2(32767) := q'[
create table zzz_temp as
select *
from dual
join some_schema.fake_table
on dual.dummy = fake_table.dummy
]';
begin
dbms_sql.parse(v_cursor_id, v_sql, dbms_sql.native);
dbms_sql.close_cursor(v_cursor_id);
exception
when others then
dbms_output.put_line
(
sqlerrm||chr(10)||
'Error occurred here: '||
regexp_substr
(
srcstr => v_sql,
pattern => '\w+',
position => dbms_sql.last_error_position()
)
);
dbms_sql.close_cursor(v_cursor_id);
end;
/
DBMS_OUTPUT:
ORA-00942: table or view does not exist
Error occurred here: fake_table
其他一些随机代码建议:
- 使用
PARALLEL(4)
而不是 PARALLEL(A, 4)
。语句级并行性几乎总是优于对象级并行性。如果您 运行 一个 table 并行,您可能希望 运行 并行整个查询。
- 尽量避免
WHEN OTHERS
。如果可能,使用更具体的错误处理程序。
我有一个带 CTAS 查询的普通 PLSQL 块。
BEGIN
EXECUTE IMMEDIATE'
CREATE TABLE ZZZ_TEMP NOLOGGING PARALLEL AS
SELECT /*+ PARALLEL(a,4) */
*
FROM
HI0XXX001.HI_TABLE_NAME a
LEFT JOIN
HR_001_GROUP B
ON
a.EMPLOYERGROUP_UD =B.ACC_NUM
LEFT JOIN
HR_002_GROUP l
ON
a.EMPLOYERGROUP_UD =l.EMPLOYERGROUP_UD
AND
a.GRP_CON_UD_COV_CONTRACT_NAME=l.GRP_CON_UD_COV_CONTRACT_NAME
';
EXCEPTION WHEN OTHERS THEN Dbms_Output.put_line(SQLERRM);
END;
让我们假设 HR_002_GROUP table 不存在于我所在的架构中 运行 这个块。有什么方法可以显示 HR_002_GROUP table 不存在的错误消息?
我发布的查询只是一个示例场景。我们在 ETL 结构中工作,我们有一大行查询脚本,将数百万数据从许多 HI table 之一插入到另一个带有前缀 VH 的小 table。我在左连接中有大约 15-30 tables。 select 每个左连接要知道哪个 table 实际上导致错误是很耗时的。
使用DBMS_SQL
代替原生动态SQL,然后使用DBMS_SQL.LAST_ERROR_POSITION()
找出语句中有错误的部分。
DBMS_SQL
不如原生动态 SQL 方便,但也更强大。有几个问题需要注意。第一个是程序 DBMS_SQL.PARSE
不仅解析命令,它还会自动 运行 DDL 命令。
下面的代码尝试使用另外两个 table 创建一个 table,其中一个显然不存在。正则表达式用于输出每个字符 从错误的位置到第一个空格。 (此代码基于this answer.)
declare
v_cursor_id integer := dbms_sql.open_cursor ();
v_sql varchar2(32767) := q'[
create table zzz_temp as
select *
from dual
join some_schema.fake_table
on dual.dummy = fake_table.dummy
]';
begin
dbms_sql.parse(v_cursor_id, v_sql, dbms_sql.native);
dbms_sql.close_cursor(v_cursor_id);
exception
when others then
dbms_output.put_line
(
sqlerrm||chr(10)||
'Error occurred here: '||
regexp_substr
(
srcstr => v_sql,
pattern => '\w+',
position => dbms_sql.last_error_position()
)
);
dbms_sql.close_cursor(v_cursor_id);
end;
/
DBMS_OUTPUT:
ORA-00942: table or view does not exist
Error occurred here: fake_table
其他一些随机代码建议:
- 使用
PARALLEL(4)
而不是PARALLEL(A, 4)
。语句级并行性几乎总是优于对象级并行性。如果您 运行 一个 table 并行,您可能希望 运行 并行整个查询。 - 尽量避免
WHEN OTHERS
。如果可能,使用更具体的错误处理程序。