如何在错误处理过程中捕获无效的 SQL
How to capture a invalid SQL in a error handling procedure
我们有一个通用的错误处理程序,我们在其他程序中使用它来将错误捕获为通用错误table。
插入table时出错的语句如下,少了一个单引号。 (开头缺少单引号。target err')
这条语句是INSERT语句中的v_err_stmt值。
insert into temp_census (ERROR_DATE, sis_table , census_table )
values(current_timestamp, target err','target error test')
错误信息是
SQL 编译错误:位置 53 处的语法错误行 2 意外 'err'。解析错误行 2 在位置 78 附近 ''.
程序如下
CREATE OR REPLACE PROCEDURE SNOW_ERROR_CAPTURE(p_batch_id number, p_job_name varchar2,p_error_desc varchar2, p_err_stmt varchar2)
returns varchar(20000)
language sql
as
$$
declare
v_err_stmt varchar2;
v_error_desc varchar2;
v_job_name varchar2;
v_batch_id number;
count number;
begin
if (p_batch_id IS NULL) then
v_batch_id :=0;
else
v_batch_id :=p_batch_id;
end if;
if (p_job_name IS NULL) then
v_job_name :='UNknown';
else
v_job_name :=p_job_name;
end if;
if (p_error_desc IS NULL) then
v_error_desc :='UNknown';
else
v_error_desc :=p_error_desc;
end if;
if (p_err_stmt IS NULL) then
v_err_stmt :='UNknown';
else
v_err_stmt :=p_err_stmt;
end if;
let _sql varchar := 'insert into BATCH_ERROR_LOG
(ERROR_DATE , BATCH_ID, JOB_NAME, DESCRIPTION, ERROR_STMT )
values
(current_timestamp ,' || v_batch_id || ',''' || v_job_name || ''',''' || v_error_desc|| ''',''' || v_err_stmt || ''')';
execute immediate _sql;
--return _sql;
exception
when statement_error then
return object_construct('Error type', 'STATEMENT_ERROR',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate
);
when other then
return object_construct('Error type', 'Other error',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
end;
$$;
假设您在 sql space 中连接字符串。您使用的任何令牌都需要保证安全。所以在你 v_err_msg
你需要用 replace(v_err_msg, '\'', '\\'')
转义那些单引号
select $$insert into temp_census (ERROR_DATE, sis_table , census_table )
values(current_timestamp, target err','target error test')$$ as v_err_msg
,'SELECT ''' || replace(v_err_msg, '\'', '\\'') || ''';' as output;
给出输出
SELECT 'insert into temp_census (ERROR_DATE, sis_table , census_table ) values(current_timestamp, target err\',\'target error test\')';
有效且安全。
但是我们还需要转义任何存在的转义标记,这必须先完成。因此你需要使用
select $$word 'quoted' and with slash \ $$ as v_err_msg
,'SELECT ''' || replace(replace(v_err_msg, '\', '\\'), '\'', '\\'') || ''';' as output;
给出:
SELECT 'word \'qouted\' and with slash \ ';
运行时返回输入:
'WORD 'QUOTED' AND WITH SLASH \ '
word 'quoted' and with slash \
我们有一个通用的错误处理程序,我们在其他程序中使用它来将错误捕获为通用错误table。
插入table时出错的语句如下,少了一个单引号。 (开头缺少单引号。target err')
这条语句是INSERT语句中的v_err_stmt值。
insert into temp_census (ERROR_DATE, sis_table , census_table )
values(current_timestamp, target err','target error test')
错误信息是 SQL 编译错误:位置 53 处的语法错误行 2 意外 'err'。解析错误行 2 在位置 78 附近 ''.
程序如下
CREATE OR REPLACE PROCEDURE SNOW_ERROR_CAPTURE(p_batch_id number, p_job_name varchar2,p_error_desc varchar2, p_err_stmt varchar2)
returns varchar(20000)
language sql
as
$$
declare
v_err_stmt varchar2;
v_error_desc varchar2;
v_job_name varchar2;
v_batch_id number;
count number;
begin
if (p_batch_id IS NULL) then
v_batch_id :=0;
else
v_batch_id :=p_batch_id;
end if;
if (p_job_name IS NULL) then
v_job_name :='UNknown';
else
v_job_name :=p_job_name;
end if;
if (p_error_desc IS NULL) then
v_error_desc :='UNknown';
else
v_error_desc :=p_error_desc;
end if;
if (p_err_stmt IS NULL) then
v_err_stmt :='UNknown';
else
v_err_stmt :=p_err_stmt;
end if;
let _sql varchar := 'insert into BATCH_ERROR_LOG
(ERROR_DATE , BATCH_ID, JOB_NAME, DESCRIPTION, ERROR_STMT )
values
(current_timestamp ,' || v_batch_id || ',''' || v_job_name || ''',''' || v_error_desc|| ''',''' || v_err_stmt || ''')';
execute immediate _sql;
--return _sql;
exception
when statement_error then
return object_construct('Error type', 'STATEMENT_ERROR',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate
);
when other then
return object_construct('Error type', 'Other error',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
end;
$$;
假设您在 sql space 中连接字符串。您使用的任何令牌都需要保证安全。所以在你 v_err_msg
你需要用 replace(v_err_msg, '\'', '\\'')
select $$insert into temp_census (ERROR_DATE, sis_table , census_table )
values(current_timestamp, target err','target error test')$$ as v_err_msg
,'SELECT ''' || replace(v_err_msg, '\'', '\\'') || ''';' as output;
给出输出
SELECT 'insert into temp_census (ERROR_DATE, sis_table , census_table ) values(current_timestamp, target err\',\'target error test\')';
有效且安全。
但是我们还需要转义任何存在的转义标记,这必须先完成。因此你需要使用
select $$word 'quoted' and with slash \ $$ as v_err_msg
,'SELECT ''' || replace(replace(v_err_msg, '\', '\\'), '\'', '\\'') || ''';' as output;
给出:
SELECT 'word \'qouted\' and with slash \ ';
运行时返回输入:
'WORD 'QUOTED' AND WITH SLASH \ ' |
---|
word 'quoted' and with slash \ |