Firebird Documentation IndexFirebird 1.5.6 Release NotesSQL Language Enhancements → Stored Procedure and Trigger Language (PSQL)
Firebird Home Firebird Home Prev: Data Manipulation Language (DML)Firebird Documentation IndexUp: SQL Language EnhancementsNext: New Reserved Words

Stored Procedure and Trigger Language (PSQL)

(1.5) EXECUTE STATEMENT
(1.5) New Context Variables
(1.5) Enhancements to Exception Handling in PSQL
(1.5) LEAVE | BREAK statement
(1.5) Valid PLAN statements can now be included in triggers
(1.5) Empty BEGIN..END blocks
(1.5) Declare and define local variable in single statement

The following enhancements have been made to PSQL, the set of language extensions available for writing stored procedures and triggers.

(1.5) EXECUTE STATEMENT

Alex Peshkov

EXECUTE STATEMENT "string" is a PSQL extension which takes a string that is a valid dynamic SQL statement and executes it as if it had been submitted to DSQL.

Available in triggers and stored procedures.

Syntax Patterns

The syntax may have three forms.-

Syntax 1

Executes "string> as an SQL operation that does not return any data rows, viz. INSERT, UPDATE, DELETE, EXECUTE PROCEDURE or any DDL statement except CREATE/DROP DATABASE.

  EXECUTE STATEMENT <string>;
          

Example

  CREATE PROCEDURE DynamicSampleOne (Pname VARCHAR(100))
  AS
  DECLARE VARIABLE Sql VARCHAR(1024);
  DECLARE VARIABLE Par INT;
  BEGIN
     SELECT MIN(SomeField) FROM SomeTable INTO :Par;
     Sql = 'EXECUTE PROCEDURE ' || Pname || '(';
     Sql = Sql || CAST(Par AS VARCHAR(20)) || ')';
     EXECUTE STATEMENT Sql;
  END
          
Syntax 2

Executes "string" as an SQL operation, returning single data row. Only singleton SELECT operators may be executed with this form of EXECUTE STATEMENT.

  EXECUTE STATEMENT <string> INTO :var1, [&, :varn] ;
          

Example

  CREATE PROCEDURE DynamicSampleTwo (TableName VARCHAR(100))
  AS
  DECLARE VARIABLE Par INT;
  BEGIN
     EXECUTE STATEMENT
       'SELECT MAX(CheckField) FROM ' || TableName INTO :Par;
     IF (Par > 100) THEN
      EXCEPTION Ex_Overflow 'Overflow in ' || TableName;
  END
          
Syntax 3

Executes "string" as SQL operation, returning multiple data rows. Any SELECT operator may be executed with this form of EXECUTE STATEMENT.

  FOR EXECUTE STATEMENT <string> INTO :var1, &, :varn
    DO
     <compound-statement>;

          

Example

  CREATE PROCEDURE DynamicSampleThree (
     TextField VARCHAR(100),
     TableName VARCHAR(100))
  RETURNS (Line VARCHAR(32000))
  AS
  DECLARE VARIABLE OneLine VARCHAR(100);
  BEGIN
    Line = '';
    FOR EXECUTE STATEMENT
     'SELECT ' || TextField || ' FROM ' || TableName
     INTO :OneLine
    DO
      IF (OneLine IS NOT NULL) THEN
         Line = Line || OneLine || ' ';
    SUSPEND;
  END
          

Caveats with EXECUTE STATEMENT

The 'EXECUTE STATEMENT' DSQL string cannot contain any parameters in any syntax variation. All variable substitution into the static part of the SQL statement should be performed before the execution of EXECUTE STATEMENT.

This feature is intended only for very cautious use and should be used with all factors taken into account. It should be a rule of thumb to use EXECUTE STATEMENT only when other methods are impossible, or perform even worse than EXECUTE STATEMENT.

Caution

EXECUTE STATEMENT is potentially unsafe in several ways:

  1. There is no way to validate the syntax of the enclosed statement.

     

  2. There are no dependency checks to discover whether tables or columns have been dropped.

     

  3. Operations will be slow because the embedded statement has to be prepared every time it is executed.

     

  4. Return values are strictly checked for data type in order to avoid unpredictable type-casting exceptions. For example, the string '1234' would convert to an integer, 1234, but 'abc' would give a conversion error.

     

  5. If the stored procedure has special privileges on some objects, the dynamic statement submitted in the EXECUTE STATEMENT string does not inherit them. Privileges are restricted to those granted to the user who is executing the procedure.

(1.5) New Context Variables

Dmitry Yemanov

A number of new context variables for PSQL have been implemented.

CURRENT_CONNECTION and CURRENT_TRANSACTION

These context variables return the system identifier of the active connection or the current transaction context, respectively. Return type is INTEGER. Available in DSQL and PSQL.

Important

Because these values are stored on the database header page, they will be reset after a database restore.

Syntax Patterns

  CURRENT_CONNECTION
  CURRENT_TRANSACTION
        

Examples

  SELECT CURRENT_CONNECTION FROM RDB$DATABASE;

  NEW.TXN_ID = CURRENT_TRANSACTION;

  EXECUTE PROCEDURE P_LOGIN(CURRENT_CONNECTION);
        

ROW_COUNT

Returns an integer, the number of rows affected by the last DML statement. Available in PSQL, in the context of the procedure or trigger module.

Currently returns zero from a SELECT statement.

Syntax Pattern

  ROW_COUNT
        

Examples

  UPDATE TABLE1 SET FIELD1 = 0 WHERE ID = :ID;
  IF (ROW_COUNT = 0) THEN
   INSERT INTO TABLE1 (ID, FIELD1) VALUES (:ID, 0);
        

Note

ROW_COUNT cannot be used for checking the rows affected by an EXECUTE STATEMENT command.

SQLCODE and GDSCODE

Each context variable returns an integer which is the numeric error code for the active exception. Available in PSQL, within the scope of the particular exception handling block. Both will evaluate to zero outside the block.

The GDSCODE variable returns a numeric representation of the GDS (ISC) error code, e.g. '335544349L' will return 335544349.

A 'WHEN SQLCODE' or 'WHEN ANY' exception block will catch a non-zero value for the SQLCODE variable and return zero for GDSCODE. Only a 'WHEN GDSCODE' block can catch a non-zero GDSCODE variable (and will return zero in SQLCODE).

If a user-defined exception is thrown, both SQLCODE and GDSCODE variables contain zero, regardless of the exception handling block type.

Syntax Pattern

  SQLCODE
  GDSCODE
        

Example

BEGIN
   ...
   WHEN SQLCODE -802 DO
     EXCEPTION E_EXCEPTION_1;
   WHEN SQLCODE -803 DO
     EXCEPTION E_EXCEPTION_2;
   WHEN ANY DO
     EXECUTE PROCEDURE P_ANY_EXCEPTION(SQLCODE);
END
        

See also the EXCEPTION HANDLING ENHANCEMENTS, below, and the document README.exception_handling in the firebird2/doc/sql.extensions branch of the Firebird CVS tree.

INSERTING, UPDATING and DELETING

Three pseudo-Boolean expressions that can be tested to determine the type of DML operation being executed. Available in PSQL, only in triggers. Intended for use with multi-action triggers (see the DML section, above).

Syntax Pattern

  INSERTING
  UPDATING
  DELETING
        

Example

  IF (INSERTING OR UPDATING) THEN
  BEGIN
    IF(NEW.SERIAL_NUM IS NULL) THEN
      NEW.SERIAL_NUM = GEN_ID(G_GENERATOR_1, 1);
        

(1.5) Enhancements to Exception Handling in PSQL

Dmitry Yemanov

The common syntax for an EXCEPTION statement in PSQL is:

   EXCEPTION [name [value]];
      

The enhancements in 1.5 allow you to

  1. define a run-time message for a named exception

     

  2. re-initiate (re-raise) a caught exception within the scope of the exception block

     

  3. Obtain a numeric error code for a caught exception

1) Run-time exception messaging

Syntax Pattern

  EXCEPTION <exception_name> <message_value>;
        

Examples

a)

EXCEPTION E_EXCEPTION_1 'Error!';
        

b)

EXCEPTION
  E_EXCEPTION_2 'Wrong type for record with ID=' || new.ID;
        

2) Re-raising an exception

Note

This has no effect outside an exception block.

Syntax Pattern

  EXCEPTION;
        

Examples

a)

  BEGIN
    ...
    WHEN SQLCODE -802 DO
      EXCEPTION E_ARITH_EXCEPT;
    WHEN SQLCODE -802 DO
      EXCEPTION E_KEY_VIOLATION;
    WHEN ANY THEN
      EXCEPTION;
  END
        

b)

  WHEN ANY DO
  BEGIN
     INSERT INTO ERROR_LOG (...) VALUES (SQLCODE, ...);
     EXCEPTION;
  END
        

3) Run-time error codes

See SQLCODE / GDSCODE (above).

(1.5) LEAVE | BREAK statement

Terminates the flow in a loop, causing flow of control to move to the statement following the END statement that completes that loop. Available for WHILE, FOR SELECT and FOR EXECUTE language constructs only, otherwise a parser error will be thrown. Available in triggers as well as stored procedures.

Important

The SQL-99 standard keyword LEAVE deprecates the existing use of BREAK.

Syntax Pattern

  LEAVE;
      

Examples

i)

  BEGIN
     <statements>;
   IF (<conditions>) THEN 
     LEAVE;
   <statements>;
  END
      

ii)

  WHILE (<condition>) DO
    BEGIN
      <statements>;
      WHEN ... DO
        LEAVE;
    END
      

The condition that branches to a LEAVE statement must be inside a block that is controlled by a looping construct (i.e., WHILE or FOR SELECT...INTO...DO).

Important

It is emphasised that LEAVE will not terminate other types of BEGIN...END block.

Note

LEAVE | BREAK and EXIT statements can now be used in triggers.

(1.5) Valid PLAN statements can now be included in triggers

Ignacio J. Ortega

Until now, a trigger containing a PLAN statement would be rejected by the compiler. Now, a valid plan can be included and will be used.

(1.5) Empty BEGIN..END blocks

Dmitry Yemanov

Empty BEGIN..END blocks in PSQL modules are now legal. For example, you can now write "stub" modules like

  CREATE TRIGGER BI_ATABLE FOR ATABLE
  ACTIVE BEFORE INSERT POSITION 0
  AS
  BEGIN
  END ^
      

(1.5) Declare and define local variable in single statement

Claudio Valderrama

Simplifies syntax and allows local variables to be declared and defined (or initialized) in one statement.

Syntax Pattern

  DECLARE [VARIABLE] name <variable_type> [{'=' | DEFAULT} value];
      

Example

  DECLARE my_var INTEGER = 123;
      
Prev: Data Manipulation Language (DML)Firebird Documentation IndexUp: SQL Language EnhancementsNext: New Reserved Words
Firebird Documentation IndexFirebird 1.5.6 Release NotesSQL Language Enhancements → Stored Procedure and Trigger Language (PSQL)