How to Commit/Rollback stored procedure based on return value in Snowflake?

雨燕双飞 提交于 2020-06-17 13:07:08

问题


I have a javascript stored procedure that return boolean. I want to be able to call this stored procedure inside a transaction and test the return value before committing the transaction.

BEGIN;
SET result = CALL my_stored_proc();

IF $result = true 
COMMIT;
ELSE
ROLLBACK;

The stored procedure will return false if there is an exception or if there is some missing values based on business logic.

How do I achieve this in Snowflake?


EDIT: I tried the following and it did not work. The transaction remains open and the statements executed inside the stored proc are not rolled back until an explicit ROLLBACK statement is issued.

USE COMMON;


CREATE TABLE LOG
(
LOG_ID INT IDENTITY(1, 1) NOT NULL CONSTRAINT PK_LOG_ID PRIMARY KEY,
LOG_LEVEL VARCHAR (50) NOT NULL,
LOGGER VARCHAR (500) NOT NULL,
MESSAGE VARCHAR NOT NULL,
EXCEPTION VARCHAR NULL,
APPLICATION_NAME VARCHAR(500) NOT NULL,
LOGGED_ON DATETIME DEFAULT TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP()) NOT NULL,
LOGGED_BY VARCHAR(200) DEFAULT CURRENT_USER() NOT NULL
);

CREATE OR REPLACE PROCEDURE TEST_TRANSACTION() 
RETURNS VARCHAR 
LANGUAGE javascript 
EXECUTE AS CALLER
AS 
$$
snowflake.execute({sqlText:`
INSERT
            INTO
                COMMON.LOG (LOG_LEVEL, LOGGER, MESSAGE, EXCEPTION, APPLICATION_NAME)
            VALUES ('DEBUG', 'TEST_TRANSACTION', 'This is a test transaction.', '', 'DATA LOADER'); 
`});
snowflake.execute({sqlText:`
INSERT
            INTO
                COMMON.LOG (LOG_LEVEL, LOGGER, MESSAGE, EXCEPTION, APPLICATION_NAME)
            VALUES ('DEBUG', 'TEST_TRANSACTION', 'This message should not be in the logs.', '', 'DATA LOADER'); 
`});

throw 'Test error'
$$
;
-- Run the next 3 lines as a batch
BEGIN;
CALL COMMON.TEST_TRANSACTION(); -- This Fails
COMMIT; -- Commit is NOT executed

SELECT * FROM COMMON.LOG WHERE LOGGER = 'TEST_TRANSACTION'; -- The insert is successful & the transaction is still OPEN

How do I rollback the statements executed inside the stored procedure?


回答1:


I recommend reading through this document as it offers several examples and methods to do what you are asking.

https://docs.snowflake.com/en/sql-reference/stored-procedures-usage.html#transaction-management




回答2:


So it turns out that you CAN issue transaction control commands (BEGIN, COMMIT, ROLLBACK) inside a stored procedure. I can being the transaction, check the return value inside the stored procedure and decide to COMMIT or ROLLBACK.

Someone should update the snowflake documentation.

CREATE OR REPLACE PROCEDURE TEST_TRANSACTION(result BOOLEAN) 
RETURNS BOOLEAN NOT NULL 
LANGUAGE javascript 
EXECUTE AS CALLER
AS 
$$
snowflake.execute({sqlText:`BEGIN;`});

snowflake.execute({sqlText:`
INSERT
            INTO
                COMMON.LOG (LOG_LEVEL, LOGGER, MESSAGE, EXCEPTION, APPLICATION_NAME)
            VALUES ('DEBUG', 'TEST_TRANSACTION', 'This is a test transaction.', '', 'DATA LOADER'); 
`});
snowflake.execute({sqlText:`
INSERT
            INTO
                COMMON.LOG (LOG_LEVEL, LOGGER, MESSAGE, EXCEPTION, APPLICATION_NAME)
            VALUES ('DEBUG', 'TEST_TRANSACTION', 'This message should not be in the logs.', '', 'DATA LOADER'); 
`});

if ( RESULT ) { snowflake.execute( {sqlText: "COMMIT" }) } 
    else {
        snowflake.execute( {sqlText: "ROLLBACK" }) };

return true;
$$
;


来源:https://stackoverflow.com/questions/62132365/how-to-commit-rollback-stored-procedure-based-on-return-value-in-snowflake

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!