Example 1: Using the SIGNAL and RETURN statements, multiline comments, and stored functions The example uses a table, NEXT_KEY_TABLE, to maintain a list of key names and their current values. In this example, only a single key is created with the name EMPLOYEE_ID. Each time the function is called, it fetches the value from the NEXT_KEY_ TABLE and returns the next value. If the named key is not found, an error is returned (SQLSTATE 22023 is defined as "invalid parameter value"). SQL> CREATE DOMAIN key_name cont> CHAR(31) cont> CHECK (VALUE IS NOT NULL) cont> NOT DEFERRABLE; SQL> -- SQL> CREATE TABLE next_key_table ( cont> next_key_val INTEGER NOT NULL, cont> next_key_name key_name UNIQUE); SQL> -- SQL> INSERT INTO next_key_table (next_key_name, next_key_val) cont> VALUES ('EMPLOYEE_ID', 0); 1 row inserted SQL> -- SQL> CREATE MODULE tools cont> LANGUAGE SQL cont> FUNCTION next_key (IN :key_name key_name) cont> RETURNS INTEGER cont> COMMENT IS 'This routine fetches the next value of the'/ cont> 'specified entry in the sequence table. The'/ cont> 'passed name is converted to uppercase before'/ cont> 'retrieval (see the DEFAULT clause for compound'/ cont> 'statements). The UPDATE ... RETURNING statement'/ cont> 'is used to fetch the new value after the update.'/ cont> 'If no entry exists, then an error is returned.'; cont> BEGIN cont> DECLARE :rc, :new_val INTEGER DEFAULT 0; cont> DECLARE :key_name_upper key_name DEFAULT UPPER(:key_name); cont> DECLARE :invalid_parameter CONSTANT CHAR(5) = '22023'; cont> -- cont> UPDATE next_key_table cont> SET next_key_val = next_key_val + 1 cont> WHERE next_key_name = :key_name_upper cont> RETURNING next_key_val cont> INTO :new_val; cont> -- cont> GET DIAGNOSTICS :rc = ROW_COUNT; cont> TRACE 'NEXT_KEY is ', COALESCE(:new_val, 'NULL'), ', RC is ', :rc; cont> -- cont> IF :rc = 0 THEN cont> TRACE 'No entry exists for KEY_NAME: ', :key_name_upper; cont> SIGNAL :invalid_parameter; cont> ELSE cont> TRACE 'Returning new value for ', :key_name_upper, :new_val; cont> RETURN :new_val; cont> END IF; cont> -- cont> END; cont> END MODULE; SQL> -- SQL> CREATE TABLE employee ( cont> employee_id INTEGER, cont> last_name CHAR(20), cont> birthday DATE); SQL> -- SQL> -- Turn on the TRACE flag so we can see the function working. SQL> -- SQL> SET FLAGS 'TRACE'; SQL> -- SQL> INSERT INTO employee (employee_id, last_name, birthday) cont> VALUES (next_key('EMPLOYEE_ID'), 'Smith', DATE'1970-1-1'); ~Xt: NEXT_KEY is 1 , RC is 1 ~Xt: Returning new value for EMPLOYEE_ID 1 1 row inserted SQL> -- SQL> INSERT INTO employee (employee_id, last_name, birthday) cont> VALUES (next_key('EMPLOYEE_ID'), 'Lee', DATE'1971-1-1'); ~Xt: NEXT_KEY is 2 , RC is 1 ~Xt: Returning new value for EMPLOYEE_ID 2 1 row inserted SQL> -- SQL> INSERT INTO employee (employee_id, last_name, birthday) cont> VALUES (next_key('EMPLOYEE_ID'), 'Zonder', DATE'1972-1-1'); ~Xt: NEXT_KEY is 3 , RC is 1 ~Xt: Returning new value for EMPLOYEE_ID 3 1 row inserted SQL> -- SQL> SELECT * FROM employee ORDER BY EMPLOYEE_ID; EMPLOYEE_ID LAST_NAME BIRTHDAY 1 Smith 1970-01-01 2 Lee 1971-01-01 3 Zonder 1972-01-01 3 rows selected SQL> -- SQL> -- Show the error if the unknown key_name is passed. SQL> -- SQL> INSERT INTO employee (employee_id, last_name, birthday) cont> VALUES (next_key('EMPLOYEEID'), 'Zonder', DATE'1972-1-1'); ~Xt: NEXT_KEY is 0 , RC is 0 ~Xt: No entry exists for KEY_NAME: EMPLOYEEID %RDB-E-SIGNAL_SQLSTATE, routine "NEXT_KEY" signaled SQLSTATE "22023" Example 2: Specifying a Secondary Error SQL> BEGIN SQL> SIGNAL SQLSTATE 'RR000' (' Compound Statement Failed'); cont> END; %RDB-E-SIGNAL_SQLSTATE, routine "(unnamed)" signaled SQLSTATE "RR000" -RDB-I-TEXT, Compound Statement Failed