从任务调用时存储过程的行为
Behaviour of stored procedures when called from a task
我正在尝试使用存储过程插入日志 table(以及其他一些不相关的功能)。此过程需要由任务自动调用,执行一些代码,然后写入 table。我可以执行上述所有操作,但是当我包含用于错误处理的 try/catch 块时,该过程不会更新日志 tables.
最小工作示例:
正在创建日志 table 和写入日志的过程,
create or replace table test_log_table (
PROC_NAME VARCHAR,
MESSAGE VARCHAR,
TIME TIMESTAMP
);
CREATE OR REPLACE PROCEDURE LOG_SP_TEST(TRGT_TABLE VARCHAR, MESSAGE VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
const PROC_NAME = Object.keys(this)[0]; // name of executing procedure
insert_sql =
`INSERT INTO ` + TRGT_TABLE+`
(
PROC_NAME,
MESSAGE,
TIME
)
VALUES
('`+ PROC_NAME +`','`+MESSAGE+`', CURRENT_TIMESTAMP());`
try{col_list_fetch_trgt = snowflake.execute(
{ sqlText: insert_sql })
}
catch(err){
return "failed: "+err
}
$$;
当手动调用该过程时,它的所有行为都符合预期
call log_sp_test('test_log_table', 'calling manually');
select * from test_log_table;
select*returns以下table
PROC_NAME
MESSAGE
TIME
LOG_SP_TEST
calling manually
2022-01-28 09:26:22.791
现在我们创建一个任务并自动再次调用该过程
-- now test calling this proc using a task
create task mytask_minute
warehouse = COMPUTE_WH
schedule = '1 minute'
as
call log_sp_test('test_log_table', 'calling via trigger');
alter task mytask_minute resume;
show tasks;
-- can then check when a task is next due to run by
select timestampdiff(second, current_timestamp, scheduled_time) as next_run, scheduled_time, current_timestamp, name, state
from table(information_schema.task_history()) where state = 'SCHEDULED' order by completed_time desc;
select * from test_log_table;
alter task mytask_minute suspend;
show tasks;
select*语句还是returns一样
PROC_NAME
MESSAGE
TIME
LOG_SP_TEST
calling manually
2022-01-28 09:26:22.791
而如果我们删除过程中的 try/catch 块,我们将得到预期的
PROC_NAME
MESSAGE
TIME
LOG_SP_TEST
calling manually
2022-01-28 09:26:22.791
LOG_SP_TEST
calling via trigger
2022-01-28 09:33:21.881
如何自动调用此过程,同时仍然能够写入日志 table 并正确处理错误?
变化:
- 在行尾使用
;
- 使用参数而不是串联
- 使用架构名称调用过程'PUBLIC.test_log_table'
程序:
CREATE OR REPLACE PROCEDURE LOG_SP_TEST(TRGT_TABLE VARCHAR, MESSAGE VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
const PROC_NAME = Object.keys(this)[0]; // name of executing procedure
insert_sql = `INSERT INTO IDENTIFIER(?) ( PROC_NAME, MESSAGE, TIME)
VALUES(?, ?, CURRENT_TIMESTAMP());`;
try{
col_list_fetch_trgt = snowflake.execute(
{ sqlText: insert_sql, binds:[TRGT_TABLE, PROC_NAME, MESSAGE] });
}
catch(err){
return "failed: "+err
}
$$;
任务:
create OR REPLACE task mytask_minute
warehouse = COMPUTE_WH
schedule = '1 minute'
as
call PUBLIC.log_sp_test('PUBLIC.test_log_table', 'calling via trigger');
输出:
我正在尝试使用存储过程插入日志 table(以及其他一些不相关的功能)。此过程需要由任务自动调用,执行一些代码,然后写入 table。我可以执行上述所有操作,但是当我包含用于错误处理的 try/catch 块时,该过程不会更新日志 tables.
最小工作示例:
正在创建日志 table 和写入日志的过程,
create or replace table test_log_table (
PROC_NAME VARCHAR,
MESSAGE VARCHAR,
TIME TIMESTAMP
);
CREATE OR REPLACE PROCEDURE LOG_SP_TEST(TRGT_TABLE VARCHAR, MESSAGE VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
const PROC_NAME = Object.keys(this)[0]; // name of executing procedure
insert_sql =
`INSERT INTO ` + TRGT_TABLE+`
(
PROC_NAME,
MESSAGE,
TIME
)
VALUES
('`+ PROC_NAME +`','`+MESSAGE+`', CURRENT_TIMESTAMP());`
try{col_list_fetch_trgt = snowflake.execute(
{ sqlText: insert_sql })
}
catch(err){
return "failed: "+err
}
$$;
当手动调用该过程时,它的所有行为都符合预期
call log_sp_test('test_log_table', 'calling manually');
select * from test_log_table;
select*returns以下table
PROC_NAME | MESSAGE | TIME |
---|---|---|
LOG_SP_TEST | calling manually | 2022-01-28 09:26:22.791 |
现在我们创建一个任务并自动再次调用该过程
-- now test calling this proc using a task
create task mytask_minute
warehouse = COMPUTE_WH
schedule = '1 minute'
as
call log_sp_test('test_log_table', 'calling via trigger');
alter task mytask_minute resume;
show tasks;
-- can then check when a task is next due to run by
select timestampdiff(second, current_timestamp, scheduled_time) as next_run, scheduled_time, current_timestamp, name, state
from table(information_schema.task_history()) where state = 'SCHEDULED' order by completed_time desc;
select * from test_log_table;
alter task mytask_minute suspend;
show tasks;
select*语句还是returns一样
PROC_NAME | MESSAGE | TIME |
---|---|---|
LOG_SP_TEST | calling manually | 2022-01-28 09:26:22.791 |
而如果我们删除过程中的 try/catch 块,我们将得到预期的
PROC_NAME | MESSAGE | TIME |
---|---|---|
LOG_SP_TEST | calling manually | 2022-01-28 09:26:22.791 |
LOG_SP_TEST | calling via trigger | 2022-01-28 09:33:21.881 |
如何自动调用此过程,同时仍然能够写入日志 table 并正确处理错误?
变化:
- 在行尾使用
;
- 使用参数而不是串联
- 使用架构名称调用过程'PUBLIC.test_log_table'
程序:
CREATE OR REPLACE PROCEDURE LOG_SP_TEST(TRGT_TABLE VARCHAR, MESSAGE VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
const PROC_NAME = Object.keys(this)[0]; // name of executing procedure
insert_sql = `INSERT INTO IDENTIFIER(?) ( PROC_NAME, MESSAGE, TIME)
VALUES(?, ?, CURRENT_TIMESTAMP());`;
try{
col_list_fetch_trgt = snowflake.execute(
{ sqlText: insert_sql, binds:[TRGT_TABLE, PROC_NAME, MESSAGE] });
}
catch(err){
return "failed: "+err
}
$$;
任务:
create OR REPLACE task mytask_minute
warehouse = COMPUTE_WH
schedule = '1 minute'
as
call PUBLIC.log_sp_test('PUBLIC.test_log_table', 'calling via trigger');
输出: