Unlike stored procedures, stored functions always return a single scalar value. To return a value from a stored functions, use the RETURN statement, which immediately ends the function.

    See also

    Used forCreating a new stored function

    Available inDSQL

    Syntax

    Table 5.9.1.1 CREATE FUNCTION Statement Parameters

    The CREATE FUNCTION statement creates a new stored function. The stored function name must be unique among the names of all stored and external (legacy) functions, excluding sub-functions or functions in packages. For sub-functions or functions in packages, the name must be unique within its module (package, stored procedure, stored function, trigger).

    Note

    It is advisable to not reuse function names between global stored functions and stored functions in packages, although this is legal. At the moment, it is not possible to call a function or procedure from the global namespace from inside a package, if that package defines a function or procedure with the same name. In that situation, the function or procedure of the package will be called.

    CREATE FUNCTION is a compound statement with a header and a body. The header defines the name of the stored function, and declares input parameters and return type.

    The function body consists of optional declarations of local variables, named cursors, and subroutines (sub-functions and sub-procedures), and one or more statements or statement blocks, enclosed in an outer block that starts with the keyword BEGIN and ends with the keyword END. Declarations and statements inside the function body must be terminated with a semicolon (;).

    5.9.1.1 Statement Terminators

    Some SQL statement editors — specifically the isql utility that comes with Firebird and possibly some third-party editors — employ an internal convention that requires all statements to be terminated with a semi-colon. This creates a conflict with PSQL syntax when coding in these environments. If you are unacquainted with this problem and its solution, please study the details in the PSQL chapter in the section entitled .

    5.9.1.2 Parameters

    Each parameter has a data type.

    A collation sequence can be specified for string-type parameters, using the COLLATE clause.

    Input Parameters

    Input parameters are presented as a parenthesized list following the name of the function. They are passed by value into the function, so any changes inside the function has no effect on the parameters in the caller. The NOT NULL constraint can also be specified for any input parameter, to prevent NULL being passed or assigned to it. Input parameters may have default values. Parameters with default values specified must be added at the end of the list of parameters.

    Output Parameter

    The RETURNS clause specifies the return type of the stored function. If a function returns a string value, then it is possible to specify the collation using the COLLATE clause. As a return type, you can specify a data type, a domain name, the type of a domain (using TYPE OF), or the type of a column of a table or view (using TYPE OF COLUMN).

    5.9.1.3 Deterministic functions

    The optional DETERMINISTIC clause indicates that the function is deterministic. Deterministic functions always return the same result for the same set of inputs. Non-deterministic functions can return different results for each invocation, even for the same set of inputs. If a function is specified as deterministic, then such a function might not be called again if it has already been called once with the given set of inputs, and instead takes the result from a metadata cache.

    Note

    Current versions of Firebird do not actually cache results of deterministic functions.

    Specifying the DETERMINISTIC clause is actually something like a promise that the function will return the same thing for equal inputs. At the moment, a deterministic function is considered an invariant, and works like other invariants. That is, they are computed and cached at the current execution level of a given statement.

    1. CREATE FUNCTION FN_T
    2. RETURNS DOUBLE PRECISION DETERMINISTIC
    3. AS
    4. BEGIN
    5. RETURN rand ();
    6. END;
    7. - the function will be evaluated twice and will return 2 different values
    8. SELECT fn_t () FROM rdb $ database
    9. UNION ALL
    10. SELECT fn_t () FROM rdb $ database;
    11. - the function will be evaluated once and will return 2 identical values
    12. WITH t (n) AS (
    13. SELECT 1 FROM rdb $ database
    14. UNION ALL
    15. SELECT 2 FROM rdb $ database
    16. )
    17. SELECT n, fn_t () FROM

    5.9.1.4 SQL Security

    The SQL SECURITY clause specifies the security context for executing other routines or inserting into other tables. When SQL Security is not specified, the default value of the database is applied at runtime.

    The SQL SECURITY clause can only be specified for PSQL functions, and is not valid for functions defined in a package.

    See also in chapter Security.

    5.9.1.5 Variable, Cursor and Subroutine Declarations

    The optional declarations section, located at the start of the body of the function definition, defines variables (including cursors) and subroutines local to the function. Local variable declarations follow the same rules as parameters regarding specification of the data type. See details in the for DECLARE VARIABLE, , DECLARE FUNCTION, and .

    5.9.1.6 Function Body

    The header section is followed by the function body, consisting of one or more PSQL statements enclosed between the outer keywords BEGIN and END. Multiple BEGIN …​ END blocks of terminated statements may be embedded inside the procedure body.

    5.9.1.7 External UDR Functions

    A stored function can also be located in an external module. In this case, instead of a function body, the CREATE FUNCTION specifies the location of the function in the external module using the EXTERNAL clause. The optional NAME clause specifies the name of the external module, the name of the function inside the module, and — optionally — user-defined information. The required ENGINE clause specifies the name of the UDR engine that handles communication between Firebird and the external module. The optional AS clause accepts a string literal body, which can be used by the engine or module for various purposes.

    Warning

    External UDR (User Defined Routine) functions created using CREATE FUNCTION …​ EXTERNAL …​ should not be confused with legacy UDFs (User Defined Functions) declared using DECLARE EXTERNAL FUNCTION.

    UDFs are deprecated, and a legacy from previous Firebird functions. Their capabilities are significantly inferior to the capabilities to the new type of external UDR functions.

    5.9.1.8 Who Can Create a Function

    The CREATE FUNCTION statement can be executed by:

    • Users with the CREATE FUNCTION privilege

    The user who created the stored function becomes its owner.

    5.9.1.9 CREATE FUNCTION Examples

    1. Creating a stored function

      1. CREATE FUNCTION ADD_INT (A INT, B INT DEFAULT 0)
      2. RETURNS INT
      3. AS
      4. BEGIN
      5. RETURN A + B;

      Calling in a select:

      1. SELECT ADD_INT(2, 3) AS R FROM RDB$DATABASE

      Call inside PSQL code, the second optional parameter is not specified:

      1. MY_VAR = ADD_INT(A);
    2. Creating a deterministic stored function

      1. CREATE FUNCTION FN_E()
      2. RETURNS DOUBLE PRECISION DETERMINISTIC
      3. AS
      4. RETURN EXP(1);
      5. END
    3. Creating a stored function with table column type parameters

      Returns the name of a type by field name and value

    4. Creating an external stored function

      Create a function located in an external module (UDR). Function implementation is located in the external module udrcpp_example. The name of the function inside the module is wait_event.

      1. CREATE FUNCTION wait_event (
      2. event_name varchar (31) CHARACTER SET ascii
      3. ) RETURNS INTEGER
      4. EXTERNAL NAME 'udrcpp_example!Wait_event'
      5. ENGINE udr
    5. Creating a stored function containing a sub-function

      Creating a function to convert a number to hexadecimal format.

      1. CREATE FUNCTION INT_TO_HEX (
      2. ANumber BIGINT ,
      3. AByte_Per_Number SMALLINT = 8)
      4. RETURNS CHAR (66)
      5. AS
      6. DECLARE VARIABLE xMod SMALLINT ;
      7. DECLARE VARIABLE xResult VARCHAR (64);
      8. DECLARE FUNCTION TO_HEX (ANum SMALLINT ) RETURNS CHAR
      9. AS
      10. BEGIN
      11. RETURN CASE ANum
      12. WHEN 0 THEN '0'
      13. WHEN 1 THEN '1'
      14. WHEN 2 THEN '2'
      15. WHEN 3 THEN '3'
      16. WHEN 4 THEN '4'
      17. WHEN 5 THEN '5'
      18. WHEN 6 THEN '6'
      19. WHEN 7 THEN '7'
      20. WHEN 8 THEN '8'
      21. WHEN 9 THEN '9'
      22. WHEN 10 THEN 'A'
      23. WHEN 11 THEN 'B'
      24. WHEN 12 THEN 'C'
      25. WHEN 13 THEN 'D'
      26. WHEN 14 THEN 'E'
      27. WHEN 15 THEN 'F'
      28. ELSE NULL
      29. END;
      30. END
      31. BEGIN
      32. xMod = MOD (ANumber, 16);
      33. ANumber = ANumber / 16;
      34. xResult = TO_HEX (xMod);
      35. WHILE (ANUMBER> 0) DO
      36. BEGIN
      37. xMod = MOD (ANumber, 16);
      38. ANumber = ANumber / 16;
      39. xResult = TO_HEX (xMod) || xResult;
      40. END
      41. RETURN '0x' || LPAD (xResult, AByte_Per_Number * 2, '0' );
      42. END
    6. With DEFINER set for function f, user US needs only the EXECUTE privilege on f. If it were set for INVOKER, the user would also need the INSERT privilege on table t.

      1. set term ^;
      2. begin
      3. insert into t values (:i);
      4. return i + 1;
      5. end^
      6. set term ;^
      7. grant execute on function f to user us;
      8. commit;
      9. connect 'localhost:/tmp/59.fdb' user us password 'pas';
      10. select f(3) from rdb$database;

    See also, Section 5.9.2, ALTER FUNCTION, , Section 5.9.4, DROP FUNCTION,

    Used forModifying an existing stored function

    Available inDSQL

    Syntax

    1. ALTER FUNCTION funcname
    2. [ ( [ <in_params> ] ) ]
    3. RETURNS <domain_or_non_array_type> [COLLATE collation]
    4. [DETERMINISTIC]
    5. {<psql_function> | <external-module-body>}
    6. !! See syntax of CREATE FUNCTION for further rules !!

    The ALTER FUNCTION statement allows the following changes to a stored function definition:

    • the set and characteristics of input and output type

    • local variables, named cursors, and subroutines

    • code in the body of the stored procedure

    For external functions (UDR), you can change the entry point and engine name. For legacy external functions declared using DECLARE EXTERNAL FUNCTION — also known as UDFs — it is not possible to convert to PSQL and vice versa.

    After ALTER FUNCTION executes, existing privileges remain intact and dependencies are not affected.

    Caution

    Take care about changing the number and type of input parameters and the output type of a stored function. Existing application code and procedures, functions and triggers that call it could become invalid because the new description of the parameters is incompatible with the old calling format. For information on how to troubleshoot such a situation, see the article in the Appendix.

    5.9.2.1 Who Can Alter a Function

    The ALTER FUNCTION statement can be executed by:

    • Owner of the stored function

    • Users with the ALTER ANY FUNCTION privilege

    5.9.2.2 Examples of ALTER FUNCTION

    Altering a stored function

    1. ALTER FUNCTION ADD_INT(A INT, B INT, C INT)
    2. RETURNS INT
    3. AS
    4. BEGIN
    5. RETURN A + B + C;
    6. END

    See also, Section 5.9.3, CREATE OR ALTER FUNCTION, , Section 5.9.4, DROP FUNCTION

    Used forCreating a new or modifying an existing stored function

    Available inDSQL

    Syntax

    The CREATE OR ALTER FUNCTION statement creates a new stored function or alters an existing one. If the stored function does not exist, it will be created by invoking a CREATE FUNCTION statement transparently. If the function already exists, it will be altered and compiled (through ALTER FUNCTION) without affecting its existing privileges and dependencies.

    5.9.3.1 Examples of CREATE OR ALTER FUNCTION

    Create a new or alter an existing stored function

    1. CREATE OR ALTER FUNCTION ADD_INT(A INT, B INT DEFAULT 0)
    2. RETURNS INT
    3. AS
    4. BEGIN
    5. RETURN A + B;
    6. END

    See alsoSection 5.9.1, CREATE FUNCTION, , Section 5.9.4, DROP FUNCTION

    Used forDropping a stored function

    Available inDSQL

    Syntax

    1. DROP FUNCTION funcname

    Table 5.9.4.1 DROP FUNCTION Statement Parameters

    ParameterDescription

    funcname

    Stored function name. The maximum length is 63 characters. Must be unique among all function names in the database.

    The DROP FUNCTION statement deletes an existing stored function. If the stored function has any dependencies, the attempt to delete it will fail, and the appropriate error will be raised.

    5.9.4.1 Who Can Drop a Function

    The DROP FUNCTION statement can be executed by:

    • Administrators

    • Owner of the stored function

    • Users with the DROP ANY FUNCTION privilege

    5.9.4.2 Examples of DROP FUNCTION

    1. DROP FUNCTION ADD_INT;

    See alsoSection 5.9.1, CREATE FUNCTION, , Section 5.9.5, RECREATE FUNCTION

    Used forCreating a new stored function or recreating an existing one

    Available inDSQL

    Syntax

    1. RECREATE FUNCTION funcname
    2. [ ( [ <in_params> ] ) ]
    3. RETURNS <domain_or_non_array_type> [COLLATE collation]
    4. [DETERMINISTIC]
    5. {<psql_function> | <external-module-body>}
    6. !! See syntax of for further rules !!

    The RECREATE FUNCTION statement creates a new stored function or recreates an existing one. If there is a function with this name already, the engine will try to drop it and then create a new one. Recreating an existing function will fail at COMMIT if the function has dependencies.

    Note

    Be aware that dependency errors are not detected until the COMMIT phase of this operation.

    After a procedure is successfully recreated, existing privileges to execute the stored function and the privileges of the stored function itself are dropped.

    5.9.5.1 Examples of RECREATE FUNCTION

    Creating or recreating a stored function

    1. RECREATE FUNCTION ADD_INT(A INT, B INT DEFAULT 0)
    2. RETURNS INT
    3. AS
    4. BEGIN