Amazon Redshift, which uses PL/pgSQL for procedural logic, supports EXIT handlers in stored procedures through EXCEPTION blocks. An EXIT handler terminates the current block when a specific condition is met and transfers control to the handler code.
When migrating code from database systems that use EXIT HANDLERs (such as DB2, Teradata, or other systems) to Snowflake, SnowConvert AI transforms these constructs into equivalent Snowflake Scripting exception handling mechanisms.
An EXIT HANDLER causes the procedure to exit the current block and return control to the caller after executing the handler code. In Snowflake, this behavior is emulated using EXCEPTION blocks with appropriate logic.
Redshift does not have native DECLARE EXIT HANDLER syntax. However, when converting from other database systems, the source pattern typically looks like:
-- Pattern from source systems (e.g., DB2, Teradata)DECLAREEXITHANDLERFOR condition_value
handler_action_statement;
In Redshift, exception handling uses:
BEGIN-- statementsEXCEPTIONWHEN condition THEN-- handler statements that exit the blockEND;
When migrating stored procedures from systems with EXIT HANDLER to Snowflake via Redshift, SnowConvert AI transforms them into Snowflake-compatible exception handling.
-- Example pattern from source systemCREATEPROCEDURE exit_handler_procedure()BEGINDECLAREEXITHANDLERFOR SQLEXCEPTION
BEGININSERTINTO error_log VALUES(CURRENT_TIMESTAMP,'Error occurred, exiting');ROLLBACK;END;-- Main procedure logicINSERTINTO orders VALUES(1,100.00);UPDATE inventory SET quantity = quantity -1WHERE product_id =1;-- This will NOT execute if an error occurredINSERTINTO audit_log VALUES('Transaction completed');END;
CREATEORREPLACEPROCEDURE exit_handler_procedure()RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "redshift", "convertedOn": "01/15/2025" }}'AS$$
BEGIN
-- Main procedure logic
INSERT INTO orders VALUES (1, 100.00);
UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 1;
-- This will NOT execute if an error occurred
INSERT INTO audit_log VALUES ('Transaction completed');
EXCEPTION
WHEN OTHER THEN
BEGIN
INSERT INTO error_log
VALUES (CURRENT_TIMESTAMP(), 'Error occurred, exiting');
ROLLBACK;
END;
END;
$$;
CREATEORREPLACEPROCEDURE specific_error_exit()RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "redshift", "convertedOn": "01/15/2025" }}'AS$$
BEGIN
INSERT INTO users VALUES (1, 'John');
INSERT INTO users VALUES (1, 'Jane'); -- Duplicate key
-- This will NOT execute
INSERT INTO success_log VALUES ('Completed');
EXCEPTION
WHEN OTHER EXIT THEN
CASE
WHEN (SQLSTATE = '23505') THEN
INSERT INTO error_log VALUES ('Duplicate key error')
END;
END;
$$;
CREATEPROCEDURE not_found_exit()BEGINDECLARE v_name VARCHAR(100);DECLAREEXITHANDLERFORNOT FOUND
INSERTINTO log_table VALUES('No data found, exiting');SELECTnameINTO v_name FROM employees WHERE id =9999;-- This will NOT execute if no data foundINSERTINTO results VALUES(v_name);END;
CREATEORREPLACEPROCEDURE not_found_exit()RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "redshift", "convertedOn": "01/15/2025" }}'AS$$
DECLARE
v_name VARCHAR(100);
BEGIN
SELECT name INTO v_name FROM employees WHERE id = 9999;
-- This will NOT execute if no data found
INSERT INTO results VALUES (v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO log_table VALUES ('No data found, exiting');
END;
$$;
CREATEORREPLACEPROCEDURE cursor_exit_handler()RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "redshift", "convertedOn": "01/15/2025" }}'AS$$
DECLARE
v_id INT;
v_name VARCHAR(100);
v_count INT := 0;
cur CURSOR FOR SELECT id, name FROM employees;
BEGIN
OPEN cur;
LOOP
FETCH cur INTO v_id, v_name;
IF (SQLCODE != 0) THEN
BREAK;
END IF;
-- Process each row
INSERT INTO processed_employees VALUES (v_id, v_name);
v_count := v_count + 1;
END LOOP;
CLOSE cur;
RETURN v_count;
EXCEPTION
WHEN OTHER THEN
BEGIN
INSERT INTO error_log VALUES ('Error in cursor processing');
RETURN -1;
END;
END;
$$;
Source systems that allow mixing CONTINUE and EXIT handlers in the same block present special challenges. Snowflake does not support this pattern in a single EXCEPTION block.