FirebirdSQL logo

Examples Using Named Cursors

  1. Declaring a named cursor in a trigger.

    CREATE OR ALTER TRIGGER TBU_STOCK
      BEFORE UPDATE ON STOCK
    AS
      DECLARE C_COUNTRY CURSOR FOR (
        SELECT
          COUNTRY,
          CAPITAL
        FROM COUNTRY
      );
    BEGIN
      /* PSQL statements */
    END
  2. Declaring a scrollable cursor

    EXECUTE BLOCK
      RETURNS (
        N INT,
        RNAME CHAR(63))
    AS
      - Declaring a scrollable cursor
      DECLARE C SCROLL CURSOR FOR (
        SELECT
          ROW_NUMBER() OVER (ORDER BY RDB$RELATION_NAME) AS N,
          RDB$RELATION_NAME
        FROM RDB$RELATIONS
        ORDER BY RDB$RELATION_NAME);
    BEGIN
      / * PSQL statements * /
    END
  3. A collection of scripts for creating views with a PSQL block using named cursors.

    EXECUTE BLOCK
    RETURNS (
      SCRIPT BLOB SUB_TYPE TEXT)
    AS
      DECLARE VARIABLE FIELDS VARCHAR(8191);
      DECLARE VARIABLE FIELD_NAME TYPE OF RDB$FIELD_NAME;
      DECLARE VARIABLE RELATION RDB$RELATION_NAME;
      DECLARE VARIABLE SOURCE TYPE OF COLUMN RDB$RELATIONS.RDB$VIEW_SOURCE;
      DECLARE VARIABLE CUR_R CURSOR FOR (
        SELECT
          RDB$RELATION_NAME,
          RDB$VIEW_SOURCE
        FROM
          RDB$RELATIONS
        WHERE
          RDB$VIEW_SOURCE IS NOT NULL);
      -- Declaring a named cursor where
      -- a local variable is used
      DECLARE CUR_F CURSOR FOR (
        SELECT
          RDB$FIELD_NAME
        FROM
          RDB$RELATION_FIELDS
        WHERE
          -- the variable must be declared earlier
          RDB$RELATION_NAME = :RELATION);
    BEGIN
      OPEN CUR_R;
      WHILE (1 = 1) DO
      BEGIN
        FETCH CUR_R
        INTO :RELATION, :SOURCE;
        IF (ROW_COUNT = 0) THEN
          LEAVE;
    
        FIELDS = NULL;
        -- The CUR_F cursor will use the value
        -- of the RELATION variable initiated above
        OPEN CUR_F;
        WHILE (1 = 1) DO
        BEGIN
          FETCH CUR_F
          INTO :FIELD_NAME;
          IF (ROW_COUNT = 0) THEN
            LEAVE;
          IF (FIELDS IS NULL) THEN
            FIELDS = TRIM(FIELD_NAME);
          ELSE
            FIELDS = FIELDS || ', ' || TRIM(FIELD_NAME);
        END
        CLOSE CUR_F;
    
        SCRIPT = 'CREATE VIEW ' || RELATION;
    
        IF (FIELDS IS NOT NULL) THEN
          SCRIPT = SCRIPT || ' (' || FIELDS || ')';
    
        SCRIPT = SCRIPT || ' AS ' || ASCII_CHAR(13);
        SCRIPT = SCRIPT || SOURCE;
    
        SUSPEND;
      END
      CLOSE CUR_R;
    END

DECLARE FUNCTION

Declares a sub-function

Syntax
<subfunc-forward> ::= <subfunc-header>;

<subfunc-def> ::= <subfunc-header> <psql-module-body>

<subfunc-header>  ::=
  DECLARE FUNCTION subfuncname [ ( [ <in_params> ] ) ]
  RETURNS <domain_or_non_array_type> [COLLATE collation]
  [DETERMINISTIC]

<in_params> ::=
  !! See CREATE FUNCTION Syntax !!

<domain_or_non_array_type> ::=
  !! See Scalar Data Types Syntax !!

<psql-module-body> ::=
  !! See Syntax of Module Body !!
Table 1. DECLARE FUNCTION Statement Parameters
Argument Description

subfuncname

Sub-function name

collation

Collation name

The DECLARE FUNCTION statement declares a sub-function.A sub-function is only visible to the PSQL module that defined the sub-function.

A sub-function can use variables, but not cursors, from its parent module.It can access other routines from its parent modules, including recursive calls to itself.

Sub-functions have a number of restrictions:

  • A sub-function cannot be nested in another subroutine.Subroutines are only supported in top-level PSQL modules (stored procedures, stored functions, triggers and PSQL blocks).This restriction is not enforced by the syntax, but attempts to create nested sub-functions will raise an error “feature is not supported” with detail message “nested sub function”.

  • Currently, a sub-function has no direct access to use cursors from its parent module.

A sub-function can be forward declared to resolve mutual dependencies between subroutines, and must be followed by its actual definition.When a sub-function is forward declared and has parameters with default values, the default values should only be specified in the forward declaration, and should not be repeated in subfunc_def.

Note

Declaring a sub-function with the same name as a stored function will hide that stored function from your module.It will not be possible to call that stored function.

Note

Contrary to DECLARE [VARIABLE], a DECLARE FUNCTION is not terminated by a semicolon.The END of its main BEGIN …​ END block is considered its terminator.