133
Overview of PSQL Stored Procedures A PSQL stored procedure is a self-contained program written in Firebird's PSQL language, and stored as part of a the database metadata. Once you have created a stored procedure, you can invoke it directly from an application, or substitute the procedure for a table or view in a SELECT statement. Stored procedures can receive input parameters from and return values to applications. Firebird's PSQL language includes the standard SQL data manipulation statements and some powerful procedural extensions, such as assignments, flow control, cursors, exceptions, and error handling. The PSQL language is very similar, but not identical, to the PSM (Persistent Stored Modules) extension of the SQL200x standard. The advantages of using stored procedures include: Modular design Applications that access the same database can share stored procedures, eliminating duplicate code and reducing the size of the applications. Streamlined maintenance When a procedure is updated, the changes are automatically reflected in all applications that use it without the need to recompile and relink them; applications are compiled and optimized only once for each client Improved performance Stored procedures are executed by the server, not the client, which reduces network traffic, and improves performance—especially for remote client access Calling stored procedures Stored procedures can be used both from applications using dynamic SQL access (such as applications using the ODBC, JDBC or ADO.Net technologies) and from applications using embedded SQL statements (as was common in applications written before the mid-nineties). For more information on calling stored procedures from the latter type of applications, see the Embedded SQL Manual. There are two types of stored procedures: Executable procedures that an application can call directly with the EXECUTE PROCEDURE statement. An executable procedure can optionally return values to the calling program. SELECT procedures that an application can use in place of a table or view in a SELECT statement. A select procedure must be defined to return one or more values (output parameters), or an error results. Both kinds of procedures are defined with the CREATE PROCEDURE statement and have essentially the same syntax. The difference is in how the procedure is written and how it is intended to be used. Select procedures can return more than one row, so that to the calling program they appear as a table or view. Executable procedures are routines invoked by the calling program, which can optionally return values. In fact, a single procedure can be used as a select procedure or as an executable procedure, but in general a procedure is written specifically to be used in a SELECT statement (a select procedure) or to be used in an EXECUTE PROCEDURE statement (an executable procedure). Privileges for stored procedures

Firebird 2.0 PSQL Reference Manual

  • Upload
    fabyow

  • View
    138

  • Download
    2

Embed Size (px)

Citation preview

Page 1: Firebird 2.0 PSQL Reference Manual

Overview of PSQL Stored Procedures

A PSQL stored procedure is a self-contained program written in Firebird's PSQL language, and stored as part of a the database metadata.

Once you have created a stored procedure, you can invoke it directly from an application, or substitute the procedure for a table or view in a SELECT statement. Stored procedures can receive input parameters from and return values to applications.

Firebird's PSQL language includes the standard SQL data manipulation statements and some powerful procedural extensions, such as assignments, flow control, cursors, exceptions, and error handling. The PSQL language is very similar, but not identical, to the PSM (Persistent Stored Modules) extension of the SQL200x standard.

The advantages of using stored procedures include:

• Modular design Applications that access the same database can share stored procedures, eliminating duplicate code and reducing the size of the applications.

• Streamlined maintenance When a procedure is updated, the changes are automatically reflected in all applications that use it without the need to recompile and relink them; applications are compiled and optimized only once for each client

• Improved performance Stored procedures are executed by the server, not the client, which reduces network traffic, and improves performance—especially for remote client access

Calling stored procedures

Stored procedures can be used both from applications using dynamic SQL access (such as applications using the ODBC, JDBC or ADO.Net technologies) and from applications using embedded SQL statements (as was common in applications written before the mid-nineties). For more information on calling stored procedures from the latter type of applications, see the Embedded SQL Manual.

There are two types of stored procedures:

• Executable procedures that an application can call directly with the EXECUTE PROCEDURE statement. An executable procedure can optionally return values to the calling program.

• SELECT procedures that an application can use in place of a table or view in a SELECT statement. A select procedure must be defined to return one or more values (output parameters), or an error results.

Both kinds of procedures are defined with the CREATE PROCEDURE statement and have essentially the same syntax. The difference is in how the procedure is written and how it is intended to be used. Select procedures can return more than one row, so that to the calling program they appear as a table or view. Executable procedures are routines invoked by the calling program, which can optionally return values.

In fact, a single procedure can be used as a select procedure or as an executable procedure, but in general a procedure is written specifically to be used in a SELECT statement (a select procedure) or to be used in an EXECUTE PROCEDURE statement (an executable procedure).

Privileges for stored procedures

Page 2: Firebird 2.0 PSQL Reference Manual

To use a stored procedure, a user must be the creator of the procedure or must be given EXECUTE privilege for it. A procedure executes with the privileges of the user and role currently associated with the connection (“session”).

Stored procedures themselves sometimes need access to tables or views for which a user does not – or should not – have privileges. For such cases the procedure can be granted privileges itself. These privileges are also available to the procedure during its execution, in addition to the privileges of the user/role invoking the procedure.

Creating nested and recursive procedures

A stored procedure can itself execute a stored procedure. Each time a stored procedure calls another procedure, the call is said to be nested because it occurs in the context of a previous and still active call to the first procedure. A stored procedure called by another stored procedure is known as a nested procedure.

If a procedure calls itself, it is recursive. Recursive procedures are useful for tasks that involve repetitive steps. Each invocation of a procedure is referred to as an instance, since each procedure call is a separate entity that performs as if called from an application, reserving memory and stack space as required to perform its tasks.

Error behaviour

When a procedure encounters an error – either a system error or a user-defined exception – all statements since the last SUSPEND are undone.

Since select procedures can have multiple SUSPENDs, possibly inside a loop statement, only the actions since the last SUSPEND are undone. Since executable procedures should not use SUSPEND, when an error occurs the entire executable procedure is undone (if EXIT is used, as recommended).

Altering and dropping procedures in use

You must make special considerations when making changes to stored procedures that are currently in use by other requests. A procedure is in use when it is currently executing, or if it has been compiled internally to the metadata cache by a request.

Changes to procedures are not visible to client applications until they disconnect and reconnect to the database; triggers and procedures that invoke altered procedures don’t have access to the new version until there is a point in which all clients are disconnected.

To simplify the task of altering or dropping stored procedures, it is highly recommended to perform this task during a maintenance period when no client applications are connected to the database. By doing this, all client applications see the same version of a stored procedure before and after you make an alteration.

Page 3: Firebird 2.0 PSQL Reference Manual

CREATE PROCEDURE

Purpose

Use CREATE PROCEDURE to create a new stored procedure, and define its input and output parameters, and body.

Security and prerequisites

To use a stored procedure, a user must be the creator of the procedure or must be given EXECUTE privilege for it. Firebird limits changes to database objects that currently existing procedures depend on.

Syntax

<create_proc_stmt> ::= CREATE [ OR ALTER ] PROCEDURE <proc_name> [ ( <input_params> ) ] [ RETURNS ( <output_params> ) ] AS <psql_body> <proc_name> ::= <identifier>

Element Description

proc_name Name of the procedure. Must be unique among procedure, table, and view names in the database

input_params List of input parameters as described on the next pages.

output_params List of output parameters as described on the next pages.

psql_body A PSQL program

Semantics

CREATE PROCEDURE defines a new stored procedure to a database. A stored procedure is a self-contained program written in the PSQL language, and stored as part of a database's metadata. Stored procedures can receive input parameters from and return values to applications.

If the optional OR ALTER clause is pecified, the statement that will either create a new procedure (if it does not already exist) or alter it (if

it already exists) and recompile it. The CREATE OR ALTER syntax preserves existing dependencies and privileges.

Examples

The following procedure, SUB_TOT_BUDGET, takes a department number as its input parameter, and returns the total, average, minimum, and maximum budgets of departments with the specified HEAD_DEPT.

/* Compute total, average, smallest, and largest de partment budget. *Parameters: * department id * *Returns:

Page 4: Firebird 2.0 PSQL Reference Manual

* total budget * average budget * min budget * max budget */ CREATE PROCEDURE SUB_TOT_BUDGET (HEAD_DEPT CHAR(3)) RETURNS (tot_budget DECIMAL(12, 2), avg_budget DECIMAL(12, 2), min_budget DECIMAL(12, 2), max_budget DECIMAL(12, 2)) AS BEGIN SELECT SUM(BUDGET), AVG(BUDGET), MIN(BUDGET), MA X(BUDGET) FROM DEPARTMENT WHERE HEAD_DEPT = :head_dept INTO :tot_budget, :avg_budget, :min_budget, :max_budget; EXIT; END

See also

PROCEDURES – INPUT PARAMETERS, PROCEDURES – OUTPUT PARAMETERS, ALTER PROCEDURE, DROP PROCEDURE

Page 5: Firebird 2.0 PSQL Reference Manual

PROCEDURES – INPUT PARAMETERS

Purpose

Use input parameters to specify input values to the procedure.

Syntax

<input_params> ::= <input_param> | <input_param> , <input_params> <input_param> ::= <param_name> <psql_type> [ { = | DEFAULT } <para m_default> ] <param_name> ::= <identifier> <param_default> ::= <psql_constant> | <psql_sys_fun>

Semantics

Input parameters are local variables that contain copies of values passed to it in the procedure call. New values assigned to input parameters during execution of the body are local to that body and not visible to the caller.

Arguments with default values must be last in the argument list; that is, you cannot declare an argument that has no default value after any arguments that have been declared with default values. The caller must supply the values for all of the arguments preceding any that are to use their defaults.

Substitution of default values occurs at run-time. If you define a procedure with defaults (say P1), call it from another procedure (say P2) and skip some final, defaulted arguments, then the default values for P1 will be substituted by the engine at time execution P1 starts. This means that, if you change the default values for P1, it is not necessary to recompile P2.

Examples

The following procedure logs an error description, or the text 'Undefined error' if no description is given in the procedure call.

CREATE PROCEDURE fac ( n CHAR(128) = 'Undefined err or' ) AS BEGIN INSERT INTO log VALUES ( :n ); END;

See Also

CREATE PROCEDURE, ALTER PROCEDURE

Page 6: Firebird 2.0 PSQL Reference Manual

PROCEDURES – OUTPUT PARAMETERS

Purpose

Use output parameters to specify placeholders for the values that the procedure returns to the caller.

Syntax

<output_params> ::= <output_param> | <output_param> , <output_params> <output_param> ::= <param_name> <psql_type> <param_name> ::= <identifier>

Semantics

Output parameters are local variables that are placeholders for the values that the procedure body returns to the caller. When a SUSPEND statement is enountered, the values in the the output parameters are copied to the calling statement and control is – temporarily – returned to the caller.

Examples

The following procedure definition computes a factorial:

CREATE PROCEDURE fac ( n BIGINT ) RETURNS m BIGINT AS BEGIN IF (n=1) THEN m=1; ELSE EXECUTE PROCEDURE fac(n-1) INTO :m; END;

See Also CREATE PROCEDURE, ALTER PROCEDURE

Page 7: Firebird 2.0 PSQL Reference Manual

ALTER PROCEDURE

Purpose

Use ALTER PROCEDURE to change the definition of an existing stored procedure.

Security and prerequisites

A procedure can be altered by its creator, the SYSDBA user, and any users with operating system root privileges.

Syntax

<alter_proc_stmt> ::= ALTER PROCEDURE <proc_name> [ ( <input_params> ) ] [ RETURNS ( <output_params> ) ] AS <psql_body> <proc_name> ::= <identifier>

Element Description

proc_name Name of the procedure. Must be unique among procedure, table, and view names in the database

input_params List of input parameters as described on the next pages.

output_params List of output parameters as described on the next pages.

psql_body A PSQL program body

Semantics

ALTER PROCEDURE changes an existing stored procedure without affecting its dependencies. It can modify a procedure's input parameters, output parameters, and body. The complete procedure header and body must be included in the ALTER PROCEDURE statement. The syntax is exactly the same as CREATE PROCEDURE, except CREATE is replaced by ALTER.

Note: Be careful about changing the type, number, and order of input and output parameters to a procedure, since existing application code may assume the procedure has its original format.

Procedures in use are not altered until they are no longer in use. ALTER PROCEDURE changes take effect when they are committed. Changes are then reflected in all applications that use the procedure without recompiling or relinking.

Examples

The following statements alter the GET_EMP_PROJ procedure, changing the return parameter to have a datatype of VARCHAR(20):

ALTER PROCEDURE GET_EMP_PROJ (EMP_NO SMALLINT) RETURNS (PROJ_ID VARCHAR(20)) AS BEGIN

Page 8: Firebird 2.0 PSQL Reference Manual

FOR SELECT PROJ_ID FROM EMPLOYEE_PROJECT WHERE EMP_NO = :emp_no INTO :proj_id DO SUSPEND; END

See Also

CREATE PROCEDURE, DROP PROCEDURE

Page 9: Firebird 2.0 PSQL Reference Manual

DROP PROCEDURE

Purpose

Use the DROP PROCEDURE statement to delete an existing stored procedure from a database.

Security and prerequisites

The following restrictions apply to dropping procedures:

You can’t drop a procedure used by other procedures, triggers, or views; alter the other database object so that it does not reference the procedure, then drop the procedure.

• You can’t drop a procedure that is recursive or in a cyclical dependency with another procedure; you must ALTER the procedure to remove the cyclical dependency, then drop the procedure.

• You can’t drop a procedure that is currently in use by an active transaction; commit the transaction, then drop the procedure.

A procedure can be dropped by its creator, the SYSDBA user, and any users with operating system root privileges.

Syntax

<drop_proc_stmt> ::= DROP PROCEDURE <proc_name> <proc_name> ::= <identifier>

Element Description

proc_name Name of an existing stored procedure

Semantics

DROP PROCEDURE removes an existing stored procedure definition from a database. You cannot drop a procedure if another database object depends on it. Use the isql SHOW PROCEDURE command to display a list of a procedure's dependencies.

Examples

The following statement deletes a procedure:

DROP PROCEDURE GET_EMP_PROJ;

See Also

ALTER PROCEDURE, CREATE PROCEDURE

Overview of PSQL Triggers

A trigger is a self-contained PSQL routine associated with a table or view that automatically performs an action when a row in the table or view is inserted, updated, or deleted.

Page 10: Firebird 2.0 PSQL Reference Manual

A trigger is never called directly. Instead, when an application or user attempts to INSERT, UPDATE, or DELETE a row in a table or view, any triggers associated with that table or view, and that operation are automatically executed, or “fired”.

Triggers can make use of exceptions. When an exception is raised by a trigger, it returns an error message, terminates the trigger, and undoes any changes made by the trigger, unless the exception is handled by an exception handler in the trigger's PSQL main body routine.

The advantages of using triggers are:

• Automatic enforcement of data restrictions Triggers make it possible to ensure that application programs enter only valid values into columns.

• Reduced application maintenance Changes to a trigger are automatically reflected in all applications that use the associated table without the need to recompile and relink.

• Automatic logging of changes to tables An application can keep a running log of changes with a trigger that fires whenever a table is modified.

• Automatic notification of changes to the database With event alerters in triggers an application can be notified automatically when certain changes to the database take place.

Triggers are database objects, like tables, views, stored procedures, exceptions, etc.

Execution of triggers

A trigger is never explicitly called. Rather, an active trigger automatically fires when the specified action occurs on the specified table.

If a trigger performs an action that causes it to fire again – or fires another trigger that performs an action that causes it to fire – an infinite loop results. For this reason, it is important to ensure that a trigger’s actions never cause the trigger to fire, even indirectly. For example, an endless loop will occur if a trigger fires on INSERT to a table and then performs an INSERT into the same table.

Triggers and transactions

Triggers operate within the context of the transaction in the program where they are fired. Triggers are considered part of the calling program’s current unit of work. If triggers are fired in a transaction, and the transaction is rolled back, then any actions performed by the triggers are also rolled back.

Triggers and security

Triggers can be granted privileges on tables and views, just as users or procedures can be granted privileges. Use the GRANT statement to grant privileges to triggers and the REVOKE statement to revoke them again.For more information about GRANT and REVOKE, see the SQL Reference Manual.

When a user performs an action that fires a trigger, the trigger will have privileges to perform its actions if either

• the trigger has privileges for the action, or

Page 11: Firebird 2.0 PSQL Reference Manual

• the user has privileges for the action

So, for example, if a user performs an UPDATE of table A, which fires a trigger, and the trigger performs an INSERT on table B, the INSERT will occur if:

• the user has insert privileges on table B, or

• the trigger has insert privileges on table B.

If there are insufficient privileges for a trigger to perform its actions, Firebird will set the appropriate error number. The trigger program can handle this error with an error handler. If the trigger program does not handle the error, an error message will be returned to the application, and the actions of the trigger and the user application statement which led to the trigger to be fired will be undone.

The NEW and OLD pseudo tables

Triggers can use two pseudo tables in their PSQL body routines, OLD, and NEW:

• the OLD pseudo table refers to the current values in a row being updated or deleted. OLD is not used for inserts.

• The NEW pseudo table refers the set of INSERT or UPDATE values for a row. If a BEFORE trigger updates the NEW pseudo table, those updated values will used. Changing the NEW pseudo table in a AFTER trigger has no effect. The NEW pseudo table is not used for deletes.

Pseudo tables are often used to compare the values of a column before and after it is modified, or to validate the new values.

Trigger predicates

Triggers can use three pseudo variables, the so-called trigger predicates. The three variables are:

• INSERTING. This pseudo variable evaluates to true when the trigger is fired as a result of an INSERT action on the base table or view, and to false otherwise.

• UPDATING. This pseudo variable evaluates to true when the trigger is fired as a result of an UPDATE action to the base table or view, and to false otherwise.

• DELETING. This pseudo variable evaluates to true when the trigger is fired as a result of an DELETETE action to the base table or view, and to false otherwise.

Trigger predicates are particularly useful when in the PSQL routine bodies of multi-action triggers, i.e. triggers that can fire as the result of more than one type of action on the base table.

Updating views with triggers

Views that are based on joins and on aggregates cannot be updated directly. You can, however, write triggers that will perform the correct writes to the base tables when a DELETE, UPDATE, or INSERT is performed on the view. This Firebird feature turns non-updatable views into updatable views.

You can specify non default behavior for updatable views, as well. Firebird does not perform write-throughs on any view that has one or more triggers defined on it. This means that you can have complete control of what happens to any base table when users modify a view based on it.

Page 12: Firebird 2.0 PSQL Reference Manual

CREATE TRIGGER

Purpose

Use CREATE TRIGGER to create – or optionally alter – a trigger, including when it fires, and what actions it performs.

Security and prerequisites

To create a trigger the user must be SYSDBA or have full privileges on the underlying table or view.

Syntax

<create_trigger_stmt> ::= CREATE [ OR ALTER ] TRIGGER <tigger_name> FOR <r elation_name> [ACTIVE | INACTIVE] <trigger_action_clause> [ <trigger_position_clause> ] AS <psql_body> <trigger_name> ::= <identifier> <relation_name> ::= <identifier>

Element Description

trigger_name Name of the trigger; must be unique in the database

relation_name Name of the table or view that causes the trigger to fire when the specified action occurs on the table or view

Semantics

CREATE TRIGGER defines a new trigger to a database. A trigger is a self-contained program associated with a table or view that automatically performs an action when a row in the table or view is inserted, updated, or deleted.

A trigger is never called directly. Instead, when an application or user attempts to INSERT, UPDATE, or DELETE a row in a table, any triggers associated with that table and operation automatically execute, or fire. Triggers defined for UPDATE on non-updatable views fire even if no update occurs.

If the optional OR ALTER clause is pecified, the statement that will either create a new trigger (if it does not already exist) or alter it (if it already exists) and recompile it. The CREATE OR ALTER syntax preserves existing dependencies and privileges.

Examples

The following trigger, SAVE_SALARY_CHANGE, makes correlated updates to the SALARY_HISTORY table when a change is made to an employee's salary in the EMPLOYEE table:

CREATE TRIGGER SAVE_SALARY_CHANGE FOR EMPLOYEE AFTER UPDATE AS BEGIN IF (OLD.SALARY <> NEW.SALARY) THEN INSERT INTO SALARY_HISTORY

Page 13: Firebird 2.0 PSQL Reference Manual

(EMP_NO, CHANGE_DATE, UPDATER_ID, OLD_SALARY, PERCENT_CHANGE ) VALUES ( OLD.EMP_NO, 'now', USER, OLD.SALARY, (NEW.SALARY/OLD.SALARY-1) * 100 ); END;

The following trigger, SET_CUST_NO, uses a generator to create unique customer numbers when a new customer record is inserted in the CUSTOMER table:

CREATE TRIGGER SET_CUST_NO FOR CUSTOMER BEFORE INSERT AS BEGIN NEW.CUST_NO = GEN_ID(CUST_NO_GEN, 1); END;

The following trigger, POST_NEW_ORDER, posts an event named "new_order" whenever a new record is inserted in the SALES table:

CREATE TRIGGER POST_NEW_ORDER FOR SALES AFTER INSERT AS BEGIN POST_EVENT 'new_order'; END;

See also

ALTER TRIGGER, DROP TRIGGER

Page 14: Firebird 2.0 PSQL Reference Manual

TRIGGER – ACTION CLAUSE

Purpose

Use the action clause to specify which actions cause the trigger to fire

Syntax

<trigger_action_clause> ::= { BEFORE | AFTER } <trigger_action> [OR <trigger_action> [OR <trigg er_action>]] <trigger_action ::= INSERT | UPDATE | DELETE

Semantics

The trigger action clause specifies when a tirgger will fire.

• A trigger can fire before or after the changes to the underlying table occurs. This is specified with the BEFORE or AFTER keyword and specifying one of the two is obligatory.

• A trigger can fire on either an INSERT, UPDATE or DELETE operation on the base table or view, or on a combination of two or three of these. The pseudo boolean variables INSERTING, UPDATING and DELETING are available in the trigger body to let the code determine which operation caused the trigger to fire.

If the trigger is based on a view, then no automatic update to the underlying tables occur, even if the view is updateable. In this casse BEFORE is identical to AFTER, other than that all BEFORE triggers run before the AFTER triggers.

Examples

The below trigger action clause specifies that the trigger should fire before the change to the base table in case of insert and update operations:

BEFORE INSERT OR UPDATE

See also

CREATE TRIGGER, ALTER TRIGGER

Page 15: Firebird 2.0 PSQL Reference Manual

TRIGGER - POSITION CLAUSE

Purpose

Use the POSITION clause to specify the order in which multiple triggers on the same table fire.

Syntax

<trigger_position_clause> ::= POSITION <psql_integer>

Element Description

psql_integer Integer number between 0 and 32767

Sematics

Specifies firing order for triggers before the same action or after the same action; the position number must be an integer between 0 and 32767. The default position is zero, which is the first position to fire. Triggers fire in order of ascending position numbers. Trigger numbers for a table and action need not be consecutive; triggers on the same action with the same position number will fire in random order.

Examples

The following four fragments of trigger headers demonstrate how the POSITION option determines trigger firing order:

CREATE TRIGGER A FOR accounts BEFORE UPDATE POSITION 5 ... /*Trigger body follows*/ CREATE TRIGGER B FOR accounts BEFORE UPDATE POSITION 0 ... /*Trigger body follows*/ CREATE TRIGGER C FOR accounts AFTER UPDATE POSITION 5 ... /*Trigger body follows*/ CREATE TRIGGER D FOR accounts AFTER UPDATE POSITION 3 ... /*Trigger body follows*/

When this update takes place:

UPDATE accounts SET account_status = 'on_hold' WHERE account_balance <0;

The triggers fire in this order: 1. Trigger B fires. 2. Trigger A fires. 3. The update occurs. 4. Trigger D fires. 5. Trigger C fires.

Page 16: Firebird 2.0 PSQL Reference Manual

See Also

CREATE TRIGGER, ALTER TRIGGER

Page 17: Firebird 2.0 PSQL Reference Manual

ALTER TRIGGER

Purpose

Use ALTER TRIGGER to change any part of an existing trigger.

Security and prerequisites

A trigger can be altered by its creator, the SYSDBA user, and any users with operating system root privileges.

Syntax

<alter_trigger_stmt> ::= ALTER TRIGGER <trigger_name> [ACTIVE | INACTIVE] <trigger_action_clause> [ <trigger_position_clause> ] [AS <psql_body>] <trigger_name> ::= <identifier>

Semantics

ALTER TRIGGER changes the definition of an existing trigger. If any of the arguments to ALTER TRIGGER are omitted, then they default to their current values, that is the value specified by CREATE TRIGGER, or the last ALTER TRIGGER.

ALTER TRIGGER can change:

• Header information only, including the trigger activation status, when it performs its actions, the event that fires the trigger, and the order in which the trigger fires compared to other triggers.

• Body information only, the trigger statements that follow the AS clause.

• Header and trigger body information. In this case, the new trigger definition replaces the old trigger definition.

Note: To alter a trigger defined automatically by a CHECK constraint on a table, use ALTER TABLE to change the constraint definition.

Examples

The following statement modifies the trigger, SET_CUST_NO, to be inactive:

ALTER TRIGGER SET_CUST_NO INACTIVE

The next statement modifies the trigger, SET_CUST_NO, to insert a row into the table, NEW_CUSTOMERS, for each new customer:

ALTER TRIGGER SET_CUST_NO FOR CUSTOMER BEFORE INSERT AS BEGIN NEW.CUST_NO = GEN_ID(CUST_NO_GEN, 1); INSERT INTO NEW_CUSTOMERS(NEW.CUST_NO, TODAY) END

Page 18: Firebird 2.0 PSQL Reference Manual

See Also

CREATE TRIGGER, DROP TRIGGER

Page 19: Firebird 2.0 PSQL Reference Manual

DROP TRIGGER

Purpose

Use DROP TRIGGER to delete an existing user-defined trigger.

Security and prerequisites

A trigger can be altered by its creator, the SYSDBA user, and any users with operating system root privileges.

Syntax

<drop_trigger_stmt> ::= DROP TRIGGER <trigger_name> <trigger_name> ::= <identifier>

Element Description

trigger_name Name of an existing trigger

Semantics

DROP TRIGGER removes a user-defined trigger definition from the database.

System-defined triggers, such as those created for CHECK constraints, cannot be dropped. Use ALTER TABLE to drop the CHECK clause that defines the trigger. Triggers used by an active transaction cannot be dropped until the transaction is terminated.

To inactivate a trigger temporarily, use ALTER TRIGGER and specify INACTIVE in the header.

Examples

The following statement drops the trigger ADD_NEW_COMPONENT:

DROP TRIGGER ADD_NEW_COMPONENT;

See Also

ALTER TRIGGER, CREATE TRIGGER

Overview of PSQL Exceptions

An exception is a named user error message that can be raised from within a PSQL program. Exceptions are created with CREATE EXCEPTION, modified with ALTER EXCEPTION, and dropped with DROP EXCEPTION. A stored procedure raises an exception with the EXCEPTION statement.

The advantages of using named user exceptions are:

• Easier code maintenance Working with named exceptions makes the PSQL code more readable to database application maintainers and helps in standardising error conditions within the application.

Page 20: Firebird 2.0 PSQL Reference Manual

• Improved error reporting System errors like “Foreign key violation” can be caught and reraised with a more descriptive user exception, e.g. “Unkown employee number”.

• Easier internationalisation of applications Error messages can be tailored to foreign languages by simply altering the named exceptions. The PSQL program code does not need to be changed, does not even have to be available.

Like for instance tables and stored procedures, exceptions are global database objects and once defined can be used by any PSQL program that needs them. However, exceptions must be created and committed before they can be raised.

Exceptions and transactions

Exceptions are user error conditions that Firebird handles the same as system exceptions, i.e. unless caught by an exception handler, all actions by the PSQL routine raising the exception are rolled back. The exception is then passed up to the PSQL routine's caller, where the same mechanism applies. If anexception reaches the outermost PSQL routine, the error condition is passed back to the application and the entire statement that called the PSQL routine is rolled back.

For more information on catching and handling exceptions inside PSQL routines, see Chapter 4, PSQL Programs.

Differences between user exceptions and system exce ptions

In many ways, user defined exceptions and system exceptions behave in the same way, and are often handled similarly in PSQL programs and in applications programs. There are, however, the following differences:

• System exceptions have numbers (the SQLCODE and the GDSCODE) and user exceptions have identifiers (i.e. names)

• The message associated with a system exception are stored in a system-wide error message database, whereas the message associated with a user exception are stored as database objects.

Page 21: Firebird 2.0 PSQL Reference Manual

• CREATE EXCEPTION • Purpose • Use CREATE EXCEPTION to create a used-defined error – along with an associated

message – for use PSQL programs. • Security and prerequisites • Exceptions are global database objects (like tables, views, stored procedures, etc.).

Exception names must be unique. • Syntax • <create_exception_stmt> ::=

CREATE EXCEPTION <exception_name> <psql_expr> <exeption_name> ::= <identifier>

Element Description

exception_name Name of the exception

psql_expr Expression evaluating to a text message associated with the exception condition

• Semantics • CREATE EXCEPTION creates an exception, a user-defined error with an associated

message. Once created, exceptions may be raised in PSQL programs with the EXCEPTION statement.

• Examples • This SQL statement creates the exception, BAD_EMP_ID: • CREATE EXCEPTION BAD_EMP_ID 'Invalid employee numbe r.'

• See Also • ALTER EXCEPTION, DROP EXCEPTION

Page 22: Firebird 2.0 PSQL Reference Manual

• ALTER EXCEPTION • Purpose • Use ALTER EXCEPTION to changes the message associated with an existing

exception. • Security and prerequisites • An exception can be altered by its creator, the SYSDBA user, and any users with

operating system root privileges. You can alter an exception even when a stored procedure or a trigger is dependent on it

• Syntax • <alter_exception_stmt> ::=

ALTER EXCEPTION <exception_name> <plsql_expr> <exeption_name> ::= <identifier>

Element Description

exception_name Name of an existing exception

psql_expr Expression evaluating to a text value

• Semantics • ALTER EXCEPTION changes the text of the associated message of a user exception. • Examples • This statement alters the English associated message of the exception in the CREATE

EXCEPTION example into the Dutch equivalent. • ALTER EXCEPTION BAD_EMP_ID 'Werknemersnummer onbeke nd'

• See Also • CREATE EXCEPTION, DROP EXCEPTION

Page 23: Firebird 2.0 PSQL Reference Manual

DROP EXCEPTION

Purpose

Use DROP EXCEPTION to delete an exception from a database.

Security and prerequisites

The following restrictions apply to dropping exceptions:

• Exceptions used in existing procedures and triggers cannot be dropped.

• Exceptions currently in use cannot be dropped.

An exception can be dropped by its creator, the SYSDBA user, and any users with operating system root privileges.

Syntax

<drop_exception_stmt> ::= DROP EXCEPTION <execption_name> <exception_name> ::= <identifier>

Element Description

exception_name Name of an existing exception

Semantics

DROP EXCEPTION removes an exception from a database. Exceptions used in existing procedures and triggers cannot be dropped.

Note: In the isql tool, the SHOW EXCEPTION command displays a list of the exceptions' dependencies, i.e. the procedures and triggers that use the exception.

Examples

This SQL statement drops an exception:

DROP EXCEPTION BAD_EMP_ID;

See Also

CREATE EXCEPTION, ALTER EXCEPTION

Overview of PSQL Programs

A PSQL program is a self contained program unit that forms the body of a stored procedure or trigger. In this manual PSQL programs are also refered to as “PSQL routines” and “PSQL procedure/tirgger bodies”: these terms are used interchangeably.

A PSQL program consists of three parts:

Page 24: Firebird 2.0 PSQL Reference Manual

• A variable declaration section PSQL programs can declare local variables. Local variables have datatypes that match the Firebird SQL types of the same name. This section is optional.

• An executable statement section The executable section consists of a series of statements. PSQL statements are a mix of traditional procedural statements, relational SQL statements and powerful cursor processing statements. A PSQL program must contain at least one statement.

• An exception handler section PSQL has full throw/catch exeption handling. The executable section can raise exceptions, which can optionally be handled by an exception handler. If desired, the handler can re-raise the exception. Defining exception handlers is optional.

Persistent PSQL Programs can only exist as the body part of a stored procedure or trigger. However, the SQL statement EXECUTE BLOCK allows the dynamic execution of a client defined PSQL Program.

Events

Firebird “events” are named messages that the server can send to client applications that have registered an interest in such events. Events are used to announce the occurrence of a specified condition or action, usually a database change such as an INSERT, UPDATE, or DELETE.

The Firebird event mechanism enables applications to respond to actions and database changes made by other, concurrently running applications without the need for those applications to communicate directly with one another, and without incurring the expense of CPU time required for periodic polling to determine if an event has occurred.

The Firebird event mechanism consists of four parts:

• A PSQL program that posts an event (to the event manager)

• An event manager that maintains an event queue and notifies applications when an event is committed.

• A first client application (or application thread) that registers interest in the event and waits for it to occur.

• A second client application (or application thread) that uses the event-posting PSQL routine (i.e. calls a procedure or causes a trigger to fire) so that the first client (thread) can resume processing.

Events are not database objects and do not have to be declared or created before use. Event names are restricted to 78 characters in size.

Events are under transaction control. This is implemented thtough an event manager: an event is a message passed by a PSQL program to the event manager. The event manager queues the event messages for later processing:

• The event manager maintains a list of events posted to it by PSQL programs. If the transaction in which the event posting took place is commited, the event is passed on to the client application(s). If that transaction is rolled back, the posting is removed from the queue.

• Within a single transaction all postings of the same event are merged, i.e. Multiple postings of the same event within a single transaction are reported to the relevant clients as a single event when the transaction is committed.

Page 25: Firebird 2.0 PSQL Reference Manual

• The event manager also maintains a list of applications that have registered an interest in events. Each time a new event is committed, the event manager notifies interested applications that the event has occurred.

• After the interested application(s) have been notified (possibly none), the event is removed from the queue.

In general, client applications work with events in a three step process.

• Indicating an interest in specific named events to the event manager.

• Waiting for event notification, or setting up an asynchroneous notification.

• Determining which event occurred and processing that event.

The precise mechanics of handling events is described in the various language interface manuals, such as the Firebird C/C++ Programming Manual.

Page 26: Firebird 2.0 PSQL Reference Manual

PSQL Programs

Purpose

Use a PSQL program to define the actions that a stored procedure or trigger will have. PSQL programs can also be contained in the EXECUTE BLOCK SQL statement.

Security and prerequisites

PSQL programs execute within their privileges. A PSQL program gets privileges from two sources:

• privileges of the user application invoking or triggering the program

• privileges specifically granted to the enclosing stored procedure or trigger.

The total set of privileges is the sum of of both sets of privileges.

Syntax

<psql_body> ::= [ <var_decl_list> ] BEGIN <stmt_list> [ <excep_handlers> ] END;

Element Description

var_decl_list A list of variable declarations, as further defined elsewhere in this chapter.

stmt_list A list of PSQL statements as described in Chapter 7, Statements.

excep_handlers A list of exception handlers, as futher described elsewhere in this chapter.

Semantics

The body contains an optional list of local variables and their datatypes, followed by a block of statements bracketed by BEGIN and END. The block can itself include compound statements, so that there may be many levels of BEGIN/END nesting.

The final END statement terminates the routine. The final actions taken depend on the context of the PSQL program:

• In a trigger, it terminates the trigger and processing continues with the next trigger (if any) or the original action firing the trigger. If no more work is to be done, control is returned to the application.

• In an executable procedure, the final END statement returns control and current values of output parameters, if any, to the calling application.

• In a selectable procedure, the final END statement returns control to the application and sets SQLCODE to 100, which indicates there are no more rows to retrieve.

Comments

Page 27: Firebird 2.0 PSQL Reference Manual

PSQL code should be commented to aid debugging and application development. Comments are especially important in stored procedures and triggers, since they are global to the database and can be used by many different application developers.

Comments in stored procedure definitions use one of two syntaxes:

<comment> ::= /* comment_text */ -- comment till end of current line

The comment_text can be any number of lines of text. A comment can appear on the same line as code.

Example

The below example shows a basic PSQL program:

/* * Example routine with no useful functionality */ DECLARE A INTEGER = 0; BEGIN WHILE (a<1000) DO BEGIN a = a + 1; END WHEN SQLCODE -902 DO INSERT INTO err_log VALUES (CURRENT_TIME, 'Un expected error'); END;

See also

EXIT statement, SUSPEND statement.

Page 28: Firebird 2.0 PSQL Reference Manual

IDENTIFIERS IN PSQL

Purpose

Use identifiers to refer to parameters, local variables and database objects.

Syntax

<identifier> ::= <unquoted_identifier> ! <quoted_identifier> <unquoted_identifier> ::= a name starting with an alphabetic character (A- Z, a-z), restricted to 31 characters, including dollar si gns ('$'), underscores ('_'), 0 to 9, A to Z, and a to z. <quoted_identifier> ::= a name enclosed in double quotes (“), containing up to 31 characters.

Semantics

Unquoted identifiers are case insensitive, in the sense that Firebird will automatically convert the identifier to upper case.

Use quoted identifiers if you want to include spaces or other characters that are not permitted in unquoted identifiers. You can also quote an identifier if the unquoted version conflicts with a Firebird reserved keyword. Quoted identifiers are case sensitive.

Examples

Below are a few examples of valid identifiers:

table1 rdb$relations “id with spaces” “value”

See also

VARIABLE DECLARATIONS

Page 29: Firebird 2.0 PSQL Reference Manual

VARIABLE DECLARATIONS

Purpose

Use variable declarations to create local variables to hold intermediate numerical or text values, or to create local cursor definitions.

Syntax

<var_decl_list> ::= <var_decl> | <var_decl> <var_decl_list> <var_decl> ::= <scalar_declaration> | <cursor_declaration

Semantics

Local variables are declared and used within a PSQL routine. They have no meaning outside the routine. Local variables must be declared at the beginning of a PSQL program before they can be used. Each local variable requires a separate declaration statement.

Local variables come in two types:

• Scalar local variables

• These are variables that hold a single numerical or text value of the specified type.

• Cursor local variables

• These define local queries. The program body can open the query, fetch its result set, and close the result set after processing.

See also

Scalar variable declarations, Cursor variable declarations

Page 30: Firebird 2.0 PSQL Reference Manual

VARIABLE DECLARATIONS – SCALAR

Purpose

Use the scalar variable declaration syntax to define numeric or text variables.

Syntax

<scalar_declaration> ::= DECLARE [VARIABLE] <var_name> <psql_datatype> [= <psql_expr>]; <var_name> ::= <identifier>

Element Description

var_name Name of a variable. Variable names and parameter names must be unique.

psql_datatype The datatype of the variable. The variable cannot be an array type or a blob type.

psql_expr Expression with a datatype matching the variable. The expression can only refer to parameters or variables defined earlier.

Semantics

Local scalar variables are declared with a specific numerical or text datatype. When values are assigned to the variable, the value is cast to the declared type of the variable. Local variables cannot have ARRAY or BLOB types.

Local scalar variables can optionally be initialised as part of the declaration. If not explicitly initialised, local variables will be initialised to the NULL value. The values of local variables are discarded at the end of the PSQL program, unless previously assigned to an output parameter.

Note: PSQL programs can contain embedded SQL statements. In such statements, precede variables with a colon (:) to signify that they are variables rather than column names. In all other PSQL statements, you need not precede variables with a colon.

See also

Cursor variable declarations

Page 31: Firebird 2.0 PSQL Reference Manual

VARIABLE DECLARATIONS – CURSOR

Purpose

Use the cursor variable declaration syntax to define a cursor that can executed and processed in the PSQL program.

Syntax

<cursor_declaration> ::= DECLARE [VARIABLE] <cursor_name> CURSOR FOR ( <select_stmt> ); <cursor_name> ::= <identifier>

Element Description

cursor_name Name of the cursor

select_stmt A select statement as defined in the SQL Reference manual

Semantics

Cursor names are required to be unique in the given context. Within a single PSQL program cursor declarations must use unique names, and they must also not conflict with the name of a cursor that is "named", via the AS CURSOR clause in a FOR SELECT statement. However, a cursor can share its name with a scalar variable in the same PSQL program, since the operations available to each are different.

When a cursor is open, updates and deletes using the WHERE CURRENT OF clause can be used to affect the current row of the cursor, so called “positioned” updates and deletes.

All cursors which were not explicitly closed will be closed automatically on exit from the current PSQL program.

Examples

The following declaration defines a local cursor named “C”

DECLARE C CURSOR FOR ( SELECT RDB$RELATION_NAME FROM RDB$RELATIONS );

See also

OPEN statement, FETCH statement, CLOSE statement, WHERE CURRENT OF clause in the SQL Reference Manual.

Page 32: Firebird 2.0 PSQL Reference Manual

EXCEPTION HANDLERS

Purpose

Use exception handlers to catch error conditions in a PSQL program or in a specific compound statement block.

Syntax

<excep_handlers> ::= <excep_handler> ! <excep_handler> <excep_handlers> <excep_handler> ::= WHEN <error_list> DO <psql_statement>; <error_list> ::= <error> ! <error> , <error_list> <error> ::= <sqlcode_error> ! <gdscode_error> ! <user_error> ! ANY

Element Description

psql_statement A PSQL statement, typically a compound statement block

Semantics

Instead of terminating when an exception occurs, a PSQL program or compound statement block can respond to and perhaps correct the error condition by “handling” the exception, through a WHEN exception handler.

A WHEN exception handler is specific to one or more error conditions. Which error conditions the handler catches is defined by the error list following the WHEN keyword. Exceptions can be defined in one of four ways:

• By refering to the SQL error code of a system exception

• By refering to the name of a system exception

• By refering to the name of a user exception

• Or by specifying ANY to create a “catch all” exception handler

When an exception is raised within a block, Firebird:

• Seeks a handler for the exception in the current block. If no such handler is found:

• it undoes any actions performed in the block;

• backs out one level to the enclosing block and seeks a handler there. Firebird continues backing out levels and undoing actions until a handler is found. If no suitable handler is found, the PSQL program is terminated and the exception is reported to the caller.

• If a handler for the exception is found in the current or an enclosing block:

Page 33: Firebird 2.0 PSQL Reference Manual

• the error handling statement or block of statements specified in the handler are executed and

• processing continues at the statement that follows the block with the exception handler. If the handler was in the outermost block (i.e. the PSQL program body), control is returned to the calling application.

An exception that has been handled does not report the exception to the calling application, i.e. it does not return an error message.

Examples

The below example shows some valid exception handling clauses:

DECLARE a INTEGER; BEGIN a = 23 / a; WHEN SQLCODE -802 DO BEGIN a = 12; END WHEN GDSCODE arith_except DO BEGIN EXEPTION; END WHEN EXCEPTION my_error DO BEGIN EXEPTION my_error 'User defined error raised' ; END WHEN ANY DO BEGIN a = 12; EXEPTION; END END;

See also

EXCEPTION statement

Page 34: Firebird 2.0 PSQL Reference Manual

EXCEPTION HANDLERS – WHEN GDSCODE

Purpose

Use the GDSCODE error specification to create an error handler for a specific Firebird error condition.

Syntax

<gdscode_error> ::= GDSCODE <gds_error_name> <gds_error_name> ::= <identifier>

Element Description

gds_error_name The name of a Firebird system error

Semantics

GDS codes are Firebird system error codes. The abbreviation “GDS” comes from “Groton Database Systems”, the company that in the early eighties developed the first versions of what currently is the Firebird code base. GDS error codes are more fine-grained then SQL error codes.

See Appendix A for a list of GDS error codes and their meaning.

Examples

The below example shows a WHEN GDSCODE based handler:

DECLARE a INTEGER; BEGIN a = 23 / a; WHEN GDSCODE arith_except DO BEGIN EXEPTION; END END;

See also

Exception handlers, WHEN SQLCODE, WHEN EXCEPTION

Page 35: Firebird 2.0 PSQL Reference Manual

EXCEPTION HANDLERS – WHEN SQLCODE

Purpose

Use the SQLCODE error specification to create an error handler for a specific SQL error condition. SQL codes are intended to be portable between relational SQL databases.

Syntax

<gdscode_error> ::= GDSCODE <sql_error_number> <sql_error_number> ::= <psql_integer>

Element Description

sql_error_number A short, signed PSQL integer value

Semantics

SQL error codes are notionally standardised between database systems and vendors. For instance, error code 100 (“NO DATA FOUND”) always has the meaning that the last row of a result set has already been retrieved and that a next row is not available.

The below table summarizes the types of SQLCODE that a handler can process:

SQLCODE Condition Meaning

<0 SQLERROR Error: The statement did not complete

0 SUCCESS Successful completion

+1–99 SQLWARNING System warning or informational message

+100 NOT FOUND No more rows found

See Appendix A for a list of SQL error numbers and their meaning.

Page 36: Firebird 2.0 PSQL Reference Manual

Examples

The below example shows a WHEN SQLCODE based handler:

DECLARE a INTEGER; BEGIN a = 23 / a; WHEN SQLCODE -802 DO BEGIN a = 17; END END;

See also

Exception handlers, WHEN GDSCODE, WHEN EXCEPTION

Page 37: Firebird 2.0 PSQL Reference Manual

EXCEPTION HANDLERS – WHEN EXCEPTION

Purpose

Use the EXCEPTION error specification to create an error handler for a named user-defined error condition.

Syntax

<user_error> ::= EXCEPTION <exception_name> <exception_name> ::= <identifier>

Element Description

exception_name The name of a user defined exception

Semantics

Named, user-defined exceptions are global database objects that are created with the CREATE EXCEPTION statement. After creation, a PSQL routine can raise the exception condition by issuing a EXEPTION statement.

Such user exceptions can be caught in an exception handler by using the WHEN EXCEPTION syntax. In all other aspects, user exceptions are handled identically to system errors.

User-defined exceptions have a SQLCODE and GDSCODE equal to zero and cannot be caught using the WHEN SQLCODE or WHEN GDSCODE syntax.

Examples

The below example shows a WHEN SQLCODE based handler:

DECLARE a INTEGER; BEGIN a = 23 / a; WHEN SQLCODE -802 DO BEGIN a = 17; END END;

See also

Exception handlers, WHEN GDSCODE, WHEN SQLCODE

Overview of PSQL datatypes

PSQL has a varied set of datatypes, that is a subset of the types supported by Firebird's SQL language: the BLOB and ARRAY datatypes are available only in SQL and not in PSQL.

Syntax

<psql_datatype> ::= <sql_basic_type>

Page 38: Firebird 2.0 PSQL Reference Manual

<sql_basic_type> ::= <int_type> | <scaled_type> | <float_type> | <char_type> | <varchar_type> | <datetime_type>

Sematics

The various types are individually discussed on the next pages.

Examples

Below are some examples of valid PSQL data type specifications used in variable declarations:

DECLARE i INTEGER; DECLARE j BIGINT; DECLARE k DECIMAL(5,2); DECLARE l DOUBLE PRECISION; DECLARE m CHAR(64) CHARACTER SET DOS403; DECLARE n NATIONAL VARCHAR(2000); DECLARE o TIMESTAMP;

See also

VARIABLE DECLARATIONS

Page 39: Firebird 2.0 PSQL Reference Manual

INTEGER DATATYPES

Purpose

Use integer datatypes to represent values consisting of whole numbers.

Syntax

<int_type> ::= SMALLINT | INTEGER | BIGINT

Semantics

Integers are whole numbers. Firebird supports three integer datatypes, which differ in their size, i.e. In the range of numbers they can hold:

• SMALLINT is a signed 16-bit integer (range –/+ 32,768)

• INTEGER is a signed 32-bit integer (range –/+ 2,147,483,648)

• BIGINT is a signed 64-bit integer (range -/+ 9,223,372,036,854,775,807)

Attempting to store a value in an integer variable that is too small to hold the value results in a “value overflow” exception.

Examples

The below example declares a variable of type INTEGER:

DECLARE a INTEGER;

See also

SCALED DATATYPE, FLOAT DATATYPE

Page 40: Firebird 2.0 PSQL Reference Manual

SCALED DATATYPES

Purpose

Use a scaled datatype to hold numbers with fixed size fractions.

Syntax

<scaled_type> ::= {DECIMAL | NUMERIC} [(precision [, scale])]

Semantics

Firebird supports two scaled datatypes, NUMERIC and DECIMAL, for handling numeric data with a fixed decimal point, such as monetary values. You can specify optional precision and scale factors for both datatypes:

• Precision is the total number or maximum number of digits, both significant and fractional, that can appear in a column of these datatypes. The allowable range for precision is from 1 to a maximum of 18.

• Scale is the number of digits to the right of the decimal point that comprise the fractional portion of the number. The allowable range for scale is from zero to precision; in other words, scale must be less than or equal to precision.

NUMERIC and DECIMAL differ subtly in the way they handle numbers larger than the specified size. NUMERIC defines a datatype that holds a maximum of precision digits, whereas DECIMAL defines a datatype that holds at least that number of digits, and possibly more.

You can specify NUMERIC and DECIMAL datatypes without precision, in which case they are identical to INTEGER. The default value for scale is zero.

The below example declares a variable of type NUMERIC:

DECLARE a NUMERIC(5,3);

See also

INTEGER DATATYPE, FLOAT DATATYPE

Page 41: Firebird 2.0 PSQL Reference Manual

FLOAT DATATYPES

Purpose

Use floating datatypes to hold floating point numbers, i.e. variable size numbers.

Syntax

<float_type> ::= FLOAT | DOUBLE PRECISION

Semantics

Firebird provides two floating-point datatypes, FLOAT and DOUBLE PRECISION; the only difference is their size:

• FLOAT specifies a single-precision, 32-bit datatype with a precision of approximately 7 decimal digits.

• DOUBLE PRECISION specifies a double-precision, 64-bit datatype with a precision of approximately 15 decimal digits.

The precision of FLOAT and DOUBLE PRECISION is fixed by their size, but the scale is not, and you cannot control the formatting of the scale.

Use floating-point numbers when you expect the placement of the decimal point to vary, and for applications where the data values have a very wide range, such as in scientific calculations.

If the value stored is outside of the range of the precision of the floating-point number, then it is stored only approximately, with its least-significant digits treated as zeros. For example, if the type is FLOAT, you are limited to 7 digits of precision. If you insert a 10-digit number 25.33333312 into the column, it is stored as 25.33333.

Examples

The below example declares a variable of type FLOAT:

DECLARE a FLOAT;

See also

SCALED DATATYPE, INTEGER DATATYPE

Page 42: Firebird 2.0 PSQL Reference Manual

(N)CHAR DATATYPES

Purpose

Use the CHAR and NCHAR datatypes to hold text values of a fixed length.

Syntax

<char_type> ::= <char_keyword> [ ( <psql_integer> ) ] [ <char_ set_spec> ] | <nchar_keyword> [ ( <psql_integer> ) ] [ <char _set_spec> ] <char_keyword> ::= CHAR | CHARACTER <nchar_keyword> ::= NCHAR | NATIONAL CHARACTER | NATIONAL CHAR <char_set> ::= CHARACTER SET <identifier>

Semantics

The CHAR(n) datatype contains character strings with a fixed length of n characters. The maximum size is 32,767 bytes, which can be 10,992 to 32,767 characters, depending on the character size (1..3 bytes). If you do not supply n, it will default to 1, so CHAR is the same as CHAR(1).

When the string to be stored or read contains less than n characters, blanks make up the difference. If the string is larger than n, then the value is truncated.

NCHAR(n) is exactly the same as CHAR(n), except that it uses the ISO8859_1 character set by definition. Using NCHAR(n) is a shortcut for using the CHARACTER SET clause to specify the ISO8859_1 character set.

Examples

The below examples define a type to hold 32 characters in Unicode and a type to hold 128 characters in the ISO8859_1 character set (a.k.a. “latin1”):

CHAR(32) CHARACTER SET UNICODE_FSS NCHAR(128)

See also

Character sets and collation orders in the SQL Reference Manual

Page 43: Firebird 2.0 PSQL Reference Manual

(N)VARCHAR DATATYPES

Purpose

Use the VARCHAR and NCHAR VARYING datatypes to hold text values of a variable length.

Syntax

<varchar_type> ::= <varchar_keyword> ( <psql_integer> ) [ <char_s et> ] | <nvarchar_keyword> ( <psql_integer> ) <varchar_keyword> ::= CHARACTER VARYING | VARCHAR <nvarchar_keyword> ::= NCHAR VARYING | NATIONAL CHARACTER VARYING | NATIONAL CHAR VARYING <char_set> ::= CHARACTER SET <identifier>

Semantics

The VARCHAR(n) datatype contains text of varying length, up to a maximum of n characters. The maximum size is 32,767 bytes, which can be 10,992 to 32,767 characters, depending on the character size (1..3 bytes). You must supply n; there is no default to 1.

Firebird converts from variable-length character data to fixed-length character data by adding spaces to the value in the varying column until the column reaches its maximum length n. In the reverse conversion, trailing blanks are removed from the text.

The main advantage of using the VARCHAR(n) datatype are that it saves memory space during the execution of PSQL programs.

Examples

The below examples define a type to hold 32 characters in Unicode and a type to hold 128 characters in the ISO8859_1 character set (a.k.a. “latin1”):

VARCHAR(32) CHARACTER SET UNICODE_FSS NCHAR VARYING (128)

See also

Character sets and collation orders in the SQL Reference Manual

Page 44: Firebird 2.0 PSQL Reference Manual

DATE/TIME DATATYPES

Purpose

Use the date and time types to hold dates, times and timestamps.

Syntax

<datetime_type> DATE | TIME | TIMESTAMP

Semantics

Firebird supports three different date/time datatypes:

• DATE stores a date as a 32-bit longword. Valid dates are from January 1, 100 a.d. to February 29, 32768 a.d.

• TIME stores time as a 32-bit longword. Valid times are from 00:00 to 23:59.9999.

• TIMESTAMP is stored as two 32-bit longwords and is a combination of DATE and TIME.

Firebird always stores the full year value in a DATE or TIMESTAMP column, never a two-digit abbreviated value. When a client application enters a two-digit year value, Firebird uses the “sliding window” algorithm to make an inference about the century:

compare the two-digit year number entered to the current year modulo 100 If the absolute difference is greater than 50, then infer that the century of the number entered is 20, otherwise it is 19.

Examples

The below example declares a variable 'birthdate' of type DATE:

DECLATE birthdate DATE;

See also

N/A

Overview of PSQL expressions

PSQL has a rich expression syntax, that is similar to the features found in most modern procedural languages. Through the system supplied standard UDF library, PSQL has access to a wide range of numerical and string functions.

Syntax

<psql_expr_list> ::= <psql_expr> ! <psql_expr> , <psql_expr_list> <psql_expr> ::= <psql_factor>

Page 45: Firebird 2.0 PSQL Reference Manual

| <psql_binop_expr> <psql_factor> ::= - <psql_expr> | ( <psql_expr> ) | ( <select_stmt> ) | <psql_variable> | <psql_array_element> | <psql_constant> | <psql_case_expr> | <psql_cast_expr> | <psql_sequence_expr> | <psql_function> | <psql_sys_info>

Semantics

The various expression types are documented on the next pages.

Examples

See the individual system function descriptions for usage examples.

See also

N/A

Page 46: Firebird 2.0 PSQL Reference Manual

USING VARIABLES IN PSQL

Purpose

Use variable identifiers to reference parameters and local variables.

Syntax

<psql_variable> ::= <identifier> | : <identifier>

Semantics

PSQL programs can contain embedded SQL statements. In such statements, precede variables with a colon (':') to signify that they are variables rather than column names. In all other PSQL statements, you need not precede variables with a colon, although you optionally can.

Examples

The below example shows how variable references are preceded by a colon in embedded SQL statements:

DECLARE start AS TIMESTAMP; DECLARE i AS INTEGER; DECLARE elapsed AS NUMERIC(9,3); DECLARE test_id AS INTEGER; BEGIN i = 100000; start = CURRENT_TIMESTAMP; WHILE (i>0) DO i = i – 1; elapsed = CURRENT_TIMESTAMP – start; test_id = 43 UPDATE scores SET elapsed = :elapsed WHERE id = :test_id; IF (ROW_COUNT = 0) THEN INSERT INTO scores VALUES (:elapsed, :test_id ); END

See also

IDENTIFERS IN PSQL

Page 47: Firebird 2.0 PSQL Reference Manual

USING ARRAYS IN PSQL

Purpose

Use the array element syntax to reference individual elements from the SQL array datatype.

Syntax

<psql_array_element> ::= <identifier> '[' <expr_list> ']'

Semantics

The PSQL language does not support the ARRAY and BLOB datatypes as found in the SQL language. However, it can access individual elements of an array, which will be scalar types that it can handle.

Examples

DECLARE element CHAR(32); BEGIN SELECT my_array[2,5] FROM table1 INTO :element; INSERT INTO table2 VALUES (:element); END

See also

Chapter 4, PSQL Datatypes

Page 48: Firebird 2.0 PSQL Reference Manual

LITERALS

Purpose

Use any of the four syntax options to define literal, constant values in your PSQL programs.

Syntax

<psql_constant> ::= NULL | <psql_numerical_constant> | <psql_text_constant> | <psql_datetime_constant>

Semantics

PSQL allows values to be specified as literals. A special literal is NULL, often refered to as “UNKOWN”. This value can be used to signal that a data item is not available or unkown.

Note that most expressions using NULL will evaluate to NULL, because if one of the elements of the expression is unknown, then the whole expression outcome is unknown.

Examples

The below statement inserts a row with three values, the third of which is unkown.

INSERT INTO employees VALUES ( 'Paul', 123, NULL );

See also

IS NULL, IS DISTINCT FROM, Numerical literals, Text literals, Date & time literals

Page 49: Firebird 2.0 PSQL Reference Manual

NUMERICAL LITERALS

Purpose

Use the numerical constant syntax to specify numerical literals in your PSQL program.

Syntax

<psql_numerical_constant> ::= <psql_integer> | <psql_scaled_int> | <psql_float> <psql_integer> ::= a string of digits whose value fits into 64 bits . <psql_scaled_int> ::= a string of digits and a single '.', where the d igits represent a value which fits into 64 bits. <psql_float> ::= a string of digits with an optional '.', and fol lowed by an “e" or "E" and an optionally signed exponent, wh ich fits into a 64 bit IEEE standard floating point representa tion.

Semantics

A numerical constant specifief using the integer syntax is of type INTEGER. A numerical constant specified using the scaled integer syntax is of type NUMERIC, with a precision equal to the number of digits and a scale equal to the number of digits after the decimal separator ('.').

Examples

Below are three examples of valid Firebird numerical constants, all equal to 1234. The first is of type INTEGER, the second of type NUMERIC(5,1) and the third of type FLOAT.

1234 1234.0 1.234E3

See also

CAST EXPRESSION

Page 50: Firebird 2.0 PSQL Reference Manual

TEXT LITERALS

Purpose

Use the text constant syntax to define literal strings in your PSQL program, possibly specifying a specific character set for the constant.

Syntax

<psql_text_constant ::= <psql_string> | <introducer> <psql_string> <psql_string> ::= a string of characters in the database character set enclosed in single quotes; within the string two adjacent quotes are taken to mean a single embedded single quote. <introducer> ::= an underscore character ('_') followed by a char acter set name. Example: _ISO8859_1 'ààààà'

Semantics

A text literal must be enclosed in single quotation marks. Note that this differs from languages such as C/C++, Java and Basic, which enclose text strings in double quotation marks.

Within expressions and conditions, Firebird treats text literals as though they have the datatype CHAR by comparing them using blank-padded comparison semantics.

Examples

'this is a string' 'this string contains a line break' 'this is how to write it''s in a string' _ISO8859_1 'this is a string in charset ISO 8859_1'

See also

CAST EXPRESSION

Page 51: Firebird 2.0 PSQL Reference Manual

DATE, TIME AND TIMESTAMP LITERALS

Purpose

Use the date and time constant syntax to define date, time and timestamp literals in your PSQL programs.

Syntax

<psql_datetime_constant> ::= DATE <psql_string> | TIME <psql_string> | TIMESTAMP <psql_string>

Semantics

By prefixing a literal string with one of the DATE, TIME or TIMESTAMP keywords one can specify time and date literals. The strings must be of the following format:

• For the DATE form: 'mm/dd/yyyy'

• For the TIME form: 'hh:mm:ss'

• For the TIMESTAMP form: 'mm/dd/yyyy hh:mm:ss'

Time values are expressed using a 24-hour clock. Using a 12-hour clock and the AM and PM specifiers is not supported.

Examples

The below examples show literals of various time types can specified using their string equivalents.

DATE '04/14/2006' TIME '13:34:12' TIMESTAMP '04/14/2006 13:34:12'

See also

CAST EXPRESSION

Page 52: Firebird 2.0 PSQL Reference Manual

BINARY OPERATORS

Purpose

Use binary operators to perform arithmetic or string concatenation.

Syntax

<psql_binop_expr> ::= <psql_add_binop> | <psql_mul_binop> | <psql_concat_binop> | <psql_collate_binop>

Semantics

The below table lists the levels of precedence among binary operators from high to low. Conditions listed in the same row have the same precedence. As the table indicates, expression factors are evaluated before binary operators.

Element Description

factor Literals, variable names, (system) functions, sequence operators, unary minus, sub-expression, singleton select.

mul_op *, /

add_binop +, -

concat !!

collate COLLATE

Binary operators are left associative, i.e. operators of equal precendence are evaluated left to right. If either operand is NULL, the result is NULL as well.

Examples

These two expressions are equivalent:

1 + 2 + 3 (1 + 2) + 3

See also

Detailed binary operator descriptions on the next pages.

Page 53: Firebird 2.0 PSQL Reference Manual

ADDITIVE OPERATORS

Purpose

Use the plus and minus operator to perform addition and subtraction.

Syntax

<psql_add_binop> ::= <psql_expr> + <psql_expr> | <psql_expr> - <psql_expr>

Semantics

The plus ('+') operator adds two numerical values or adds an interval to a date/time value. The minus ('-') operator subtracts two numerical values, subtracts an interval from a date/time value, or calculates the interval between two date/time values.

If both operands are integer, the result is integer. If one or both are scaled values, the result is a scaled value with the combined presicion and scale. If one or both are float values, the result is a float value. If one of the two operands are date/time values, the result is a timestamp value. When subtracting two date/time values, the result is a float.

Intervals are expressed as a floating point number, representing the number of days in the interval. Fractions are used to represent intervals shorter than a day, e.g. an interval of 0.5 represents 12 hous, a half day.

Examples

The below example shows various uses of the additive operators.

DECLARE a AS INTEGER; DECLARE b AS FLOAT; DECLARE c AS TIMESTAMP; BEGIN a = 2; b = a + 0.5; c = CURRENT_TIMESTAMP + b; b = c – CURRENT_DATE; END;

See also

MULTIPLICATIVE OPERATORS

Page 54: Firebird 2.0 PSQL Reference Manual

MULTIPLICATIVE OPERATORS

Purpose

Use the times and divide operator to perform multiplication and division.

Syntax

<psql_mul_binop> ::= <psql_expr> * <psql_expr> | <psql_expr> / <psql_expr>

Semantics

The times ('*') operator multiplies two numerical values. The divide ('/') operator divides two numerical values.

If both operands are integer, the result is integer. If one or both are scaled values, the result is a scaled value with the combined presicion and scale. If one or both are float values, the result is a float value.

Examples

The below example multiplies two scaled numbers and assigns the result to a variable with sufficient scaling to hold the result.

DECLARE a AS NUMERIC(3,1) DECLARE a AS NUMERIC(3,2) DECLARE a AS NUMERIC(6,3) BEGIN a = 20.0; b = 3.14; c = a * b; END;

See also

ADDITIVE OPERATORS

Page 55: Firebird 2.0 PSQL Reference Manual

CONCATENATION OPERATOR

Purpose

Use the concatenation operator to concatenate two text strings.

Syntax

<psql_concat_binop> ::= <psql_expr> || <psql_expr>

Semantics

The concatenation ('||') operator concatenates two text values. Operands will NOT automatically be converted to text by this operator: use an explicit CAST instead.

If either operand is NULL, the concatenation evaluates to NULL as well. Note for Oracle users: this is different from the Oracle behaviour, which treats a NULL value as identical to an empty string.

The result has type VARCHAR, with a length sufficient to hold the result.

Examples

The below example creates a message from the concatenation of a CHAR field and a literal string:

SELECT TRIM(rdb$relation_name) || ' is a system tabl e' FROM rdb$relations WHERE rdb$system_flag = 1;

See also

SUBSTRING

Page 56: Firebird 2.0 PSQL Reference Manual

COLLATION ORDER OPERATOR

Purpose

Use the collation operator to cast a text string to a specific collation order.

Syntax

<psql_collation_binop> ::= <psql_expr> COLLATE <collation_name> <collation_name> ::= <identifier>

Semantics

If no collation order is specified, Firebird sorts text values by their binary order. This is the same as alphabetic order for ASCII texts. In other character sets binary ordering may not be appropiate and characters like 'e', 'é', 'ë', 'ê' and 'è' should all appear together or in sequence. This can be achieved by specifying a collation order for the character set.

Because PSQL currently only has scalar datatypes which are not ordered, specifyin a collation for a text value has no discernable effect. Of course, collation orders can be gainfully used in SQL statements that are embedded in PSQL programs. See the SQL Reference Manual for details.

Examples

The below example shows a valid use of the COLLATION operator. In this context it has no effect, because only a single text value is involved.

IF ( last_name = _ISO8851_1 'Paul' COLLATE 'DE_D E' ) THEN i=i+1;

See also

CAST Expression

Page 57: Firebird 2.0 PSQL Reference Manual

BUILT-IN FUNCTIONS

Purpose

The PSQL language supports a broad range of functions. Most of these are supported in the form of a standard system library, much like C/C++.

Syntax

<psql_function> ::= <psql_udf_call> | <psql_context_fun> | <psql_extract_fun> | <psql_length_fun> | <psql_upper_fun> | <psql_lower_fun> | <psql_substr_fun> | <psql_trim_fun>

Semantics

Next to the standard library functions, there are ten built-in functions which can be used even if the Firebird standard library is not available:

• Two context functions allow access to context variables

• One function to work with date and time elements

• Three length functions allow access to string length in various metrics

• Four frequently used string functions are built-in for convenience

The built-in functions are documented individually on the next pages.

Examples

See the individual system function descriptions for usage examples.

See also

Please refer to the SQL Reference Manual for a description of the Firebird standard function library.

Page 58: Firebird 2.0 PSQL Reference Manual

STANDARD LIBRARY FUNCTIONS

Purpose

Most functions commonly found in relational database systems are supported through the Firebird standard UDF library. Calling such functions always follows the same syntax.

Syntax

<psql_udf_call> ::= <udf_name> ( <psql_expr_list> )

Semantics

The standard function library is documented in the SQL Reference Manual.

Examples

See the individual function descriptions in the SQL Reference Manual for usage examples.

See also

Please refer to the SQL Reference Manual

Page 59: Firebird 2.0 PSQL Reference Manual

CONTEXT VARIABLE FUNCTIONS

Purpose

Use the get/set context variable functions to access and set context variables. Context variables are variables that are associated with either the current connection or the current transaction.

Security and prerequisites

To avoid DoS attacks against the Firebird Server, the number of variables stored for each transaction or session context is limited to 1000.

Syntax

<psql_context_fun> ::= RDB$GET_CONTEXT ( <psql_namespace>, <psql_var_name> ) ! RDB$SET_CONTEXT ( <psql_namespace>, <psql_var_nam e>, <psql_new_val ) <psql_namespace> ::= <psql_expr> <psql_varname> ::= <psql_expr> <psql_new_val> ::= <psql_expr>

Element Description

psql_namespace A PSQL expression evaluating to text

psql_varname A PSQL expression evaluating to text

psql_new_val A PSQL expression of any type, which will be cast to VARCHAR(255)

Semantics

The functions RDB$SET_CONTEXT and RDB$GET_CONTEXT set and retrieve the current value of a context variable. Groups of context variables with similar properties are identified by “namespace” identifiers.

• RDB$GET_CONTEXT retrieves current value of a variable. If the variable does not exist in namespace, the function returns NULL.

• RDB$SET_CONTEXT sets a value for specific variable, if it is writable. The function returns a value of 1 if the variable existed before the call and 0 otherwise.

• To delete a variable from a context, set its value to NULL.

The namespace determines the usage rules, such as whether the variables may be read and written to, and by whom. Currently three namespaces have been defined:

• 'USER_SESSION'

• 'USER_TRANSACTION'

• 'SYSTEM'

Page 60: Firebird 2.0 PSQL Reference Manual

The 'USER_SESSION' namespace is persistent for the duration of the current session (i.e. as long as the current connection is maintained). Variables can be freely created in this namespace and are read/write in nature.

The 'USER_TRANSACTION' namespace is persistent for the duration of the current transaction (i.e. as long as the current transaction is not committed or rolled back). Variables can be freely created in this namespace and are read/write in nature.

The 'SYSTEM' namespace allows read-only access to a specific set of system variables:

Variable Description

'CLIENT_ADDRESS' The wire protocol address of the remote client, represented as a string. The value is an IP address in form "xxx.xxx.xxx.xxx" for TCPv4 protocol; the local process ID forXNET protocol; and NULL for any other protocol.

'DB_NAME' Canonical name of the current database. It is either the alias name (if connection via file names is disallowed DatabaseAccess = NONE) or, otherwise, the fully expanded database file name.

'ISOLATION_LEVEL' The isolation level of the current transaction. The returned value will be one of 'READ COMMITTED', 'SNAPSHOT', 'CONSISTENCY'.

'TRANSACTION_ID' The numeric ID of the current transaction. The returned value is the same as would be returned by the CURRENT_TRANSACTION system function.

'SESSION_ID' The numeric ID of the current session. The returned value is the same as would be returned by the CURRENT_CONNECTION system function.

'CURRENT_USER' The current user. The returned value is the same as would be returned by the CURRENT_USER or USER system functions.

'CURRENT_ROLE' Current role for the connection. Returns the same value as the CURRENT_ROLE system function.

Note that the namespace and variable names are case-sensitive. Variable values are stored with datatype VARCHAR(255).

The return type of the set context function is INTEGER. The return type of the get context function is VARCHAR(255).

Examples

The below example shows how context variables can be used to simplify the creating of an audit log.

CREATE PROCEDURE set_context(User_ID VARCHAR(40), T rn_ID INTEGER) AS BEGIN RDB$SET_CONTEXT('USER_TRANSACTION', 'Trn_ID', Tr n_ID); RDB$SET_CONTEXT('USER_TRANSACTION', 'User_ID', U ser_ID); END; CREATE TABLE journal ( jrn_id integer not null primary key,

Page 61: Firebird 2.0 PSQL Reference Manual

jrn_lastuser varchar(40), jrn_lastaddr varchar(255), jrn_lasttransaction integer ); CREATE TRIGGER ui_jounal FOR journal AFTER INSERT O R UPDATE AS BEGIN new.jrn_lastuser = rdb$get_context('USER_TRANSACT ION', 'User_ID'); new.jrn_lastaddr = rdb$get_context('SYSTEM', 'CLI ENT_ADDRESS'); new.jrn_lasttransaction = rdb$get_context('USER_TRANSACTION', 'Trn_ID'); END; EXECUTE PROCEDURE set_context('skidder', 1); INSERT INTO journal(jrn_id) VALUES (0);

See also

CURRENT_USER, CURRENT_ROLE, CURRENT_CONNECTION and CURRENT_TRANSACTION

Page 62: Firebird 2.0 PSQL Reference Manual

EXTRACT FUNCTION

Purpose

Use the EXTRACT function to extract various time and date elements from a date, time or timestamp value.

Syntax

<psql_extract> ::= EXTRACT ( <timestamp_part> FROM <psql_expr> ) <timestamp_part> ::= YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | WEEKDAY | YEARDAY

Element Description

psql_expr A PSQL expression evaluating to a date/time type

Semantics

The extract function selects various specific elements from a date, time or timestamp value:

• YEAR: the year as a 4-digit number

• MONTH: the month, January equals 1

• DAY: the day of the month, an integer in the range 1 to 31

• HOUR: the hour of the day, an integer in the range 0 to 23

• MINUTE: the minute of the hour, an integer in the range 0 to 59

• SECOND: the second of the minute, an integer in the range 0 to 59

• WEEKDAY: the day of the week, Sunday equals 1

The return type of the EXTRACT function is INTEGER.

Page 63: Firebird 2.0 PSQL Reference Manual

Examples

The below example extracts the day of the week number from the current date:

DECLARE DoW AS INTEGER; BEGIN DoW = EXTRACT( WEEKDAY FROM CURRENT_DATE ); END

See also

N/A

Page 64: Firebird 2.0 PSQL Reference Manual

LENGTH FUNCTIONS

Purpose

Use the length functions to calculate the length of a text string under various metrics.

Syntax

<psql_length_fun> ::= CHAR_LENGTH ( <psql_expr> ) | CHARACTER_LENGTH ( <psql_expr> ) | OCTET_LENGTH ( <psql_expr> ) | BIT_LENGTH ( <psql_expr> )

Element Description

psql_expr A PSQL expression evaluating to text

Semantics

These functions return information about the size of strings:

• BIT_LENGTH returns the length of a string in bits

• CHAR_LENGTH and CHARACTER_LENGTH return the length of a string in characters

• OCTET_LENGTH returns the length of a string in bytes

In character sets other than ASCII, the character length can differ from the octet length.

Examples

SELECT rdb$relation_name, CHAR_LENGTH(rdb$relation_name), CHAR_LENGTH(TRIM(rdb$relation_name)) FROM rdb$relations;

See also

SUBSTRING FUNCTION

Page 65: Firebird 2.0 PSQL Reference Manual

UPPER EXPRESSION

Purpose

Use the UPPER function to change a text value to upper case.

Syntax

<psql_lower_fun> ::= UPPER ( <psql_expr> )

Element Description

psql_expr A PSQL expression evaluating to text

Semantics

The UPPER function returns the input argument converted to all upper-case characters, according to the character set of its argument.

The return type of the UPPER function is the same type as its argument. In case the argument was not a text value, the return type is CHAR(64).

Examples

The below example shows how UPPER converts characters in character set DOS850:

isql -q -ch dos850 SQL> create database 'test.fdb' user 'SYDBA' passwo rd 'masterkey'; SQL> create table t (c char(1) character set dos850 ); SQL> insert into t values ('A'); SQL> insert into t values ('E'); SQL> insert into t values ('Á');; SQL> insert into t values ('É'); SQL> select c, upper(c) from t; C UPPER ====== ====== a A e E á Á é É

See also

LOWER

Page 66: Firebird 2.0 PSQL Reference Manual

LOWER FUNCTION

Purpose

Use the LOWER function to change a text value to lower case.

Syntax

<psql_lower_fun> ::= LOWER ( <psql_expr> )

Element Description

psql_expr A PSQL expression evaluating to text

Semantics

The LOWER function returns the input argument converted to all lower-case characters, according to the character set of its argument.

The return type of the LOWER function is the same type as its argument. In case the argument was not a text value, the return type is CHAR(64).

Examples

The below example shows how LOWER converts characters in character set DOS850:

isql -q -ch dos850 SQL> create database 'test.fdb' user 'SYDBA' passwo rd 'masterkey'; SQL> create table t (c char(1) character set dos850 ); SQL> insert into t values ('A'); SQL> insert into t values ('E'); SQL> insert into t values ('Á');; SQL> insert into t values ('É'); SQL> select c, lower(c) from t; C LOWER ====== ====== A a E e Á á É é

See also

UPPER

Page 67: Firebird 2.0 PSQL Reference Manual

SUBSTRING FUNCTION

Purpose

Use the substring function to select a part of a text string.

Syntax

<psql_substring_fun> ::= SUBSTRING ( <psql_text> FROM <psql_pos> [FOR <ps ql_len>] ) <psql_text> ::= <psql_expr> <psql_pos> ::= <psql_expr> <psel_len>::= <psql_expr>

Element Description

psql_text A PSQL expression evaluating to text

psql_pos A PSQL expression evaluating to integer

psql_len A PSQL expression evaluating to integer

Semantics

The substring function will return a string consisting of the character at position <pos> and all subsequent bytes up to the end of the string. If the optional FOR clause is specified, it will return the lesser of <len> characters or the number of characters up to the end of the input string.

The first argument can be any expression, constant or identifier that evaluates to a string. <pos> starts at 1, like other SQL commands.

The <text> element can be a binary blob, or a sub_type 1 text blob with an underlying one-byte-per-character charset. Because <pos> and <length> are byte positions in this case,the function currently does not handle text blobs with Chinese or Unicode character sets.

Examples

The below example strips the first three characters from a table's column:

UPDATE table SET col_b = SUBSTRING(col_b FROM 4)

See also

N/A

Page 68: Firebird 2.0 PSQL Reference Manual

TRIM FUNCTION

Purpose

Use the TRIM function to trim leading and/or trailing characters from text values.

Syntax

<psql_trim_function> ::= TRIM ( [<trim_spec>] [<psql_trim> FROM] <psql_te xt> ) <trim_spec> ::= LEADING | TRAILING |! BOTH <psql_trim> ::= <psql_expr> <psql_text> ::= <psql_expr>

Element Description

psql_trim A PSQL expression evaluating to text

psql_text A PSQL expression evaluating to text

Semantics

The TRIM function trims characters from a text string. The default character that is being trimmed away are spaces (' '), but can be set to any character using the FROM element.

The optional trim spec parameter allows the specifaction of what to trim from the text value:

• If LEADING is specified, the action is to trim the leading (left) characters

• If TRAILING is specified, the action is to trim the trailing (right) characters

• If BOTH is specified, the action is to trim both leading characters and trailing characters from the text string.

The default trim specification is BOTH.

The return type of the TRIM function is the same as the type of the text that is being trimmed (i.e. the type of the <psql_text> expression).

Page 69: Firebird 2.0 PSQL Reference Manual

Examples

The below two examples show how TRIM may be used to trim spaces of CHAR fields or pre- and postfixes from strings:

SELECT TRIM(rdb$relation_name) || ' is a system tabl e' FROM rdb$relations WHERE rdb$system_flag = 1; SELECT rdb$relation_name, trim(leading 'RDB$' FROM rdb$relation_name) FROM rdb$relations WHERE rdb$relation_name STARTING WITH 'RDB$';

See also

N/A

Page 70: Firebird 2.0 PSQL Reference Manual

CASE EXPRESSION

Purpose

Use CASE statement to let the result of an expression to be determined by the outcome of a group of exclusive conditions.

Syntax

<psql_case_expr> ::= <psql_case_short_from> | <psql_simple_case> | <psql_searched_case> <psql_case_short_form> ::= <psql_nullif> | <psql_coalesce> | <psql_iif> <psql_simple_case> ::= CASE <psql_expr> <psql_simple_when> END | CASE <psql_expr> <psql_simple_when> ELSE <psql _expr> END <psql_simple_when> ::= WHEN <psql_expr> THEN <psql_expr> | <psql_simple_when> WHEN <psql_expr> THEN <psql _expr> <psql_searched_case> ::= CASE <psql_searched_when> END | CASE <psql_searched_when> ELSE <psql_expr> END <psql_searched_when> ::= WHEN <psql_condition> THEN <psql_expr> | <psql_searched_when> WHEN <psql_condition> TH EN <psql_expr>

Semantics

In a simple CASE expression, Firebird searches for the first WHEN ... THEN pair for which the CASE expression is equal to the WHEN expression and returns the THEN expression. If none of the WHEN ... THEN pairs meet this condition, and an ELSE clause exists, then Firebird returns the ELSE expression. Otherwise, the case expression returns null. You cannot specify the literal NULL for all the THEN expressions and the ELSE expression.

Note that a WHEN NULL clause in a simple case statement is never true: use a searched case and the IS NULL condition instead.

In a searched CASE expression, Firebird searches from left to right until it finds anoccurrence of condition that is true, and then returns the THEN expression. If no condition is found to be true, and an ELSE clause exists, Firebird returns the ELSE expression. Otherwise, the case expression returns null.

Page 71: Firebird 2.0 PSQL Reference Manual

Example

Below is an example of a simple case statement. It decodes the value of the 'status' column into a number of text values:

SELECT o.ID, o.Description, CASE o.Status WHEN 1 THEN 'confirmed' WHEN 2 THEN 'in production' WHEN 3 THEN 'ready' WHEN 4 THEN 'shipped' ELSE 'unknown status ''' || o.Status || '''' END FROM Orders o;

Below is an example of a searched case statement. It is functionally the same as the previous example, except in that it also handles the value NULL.

SELECT o.ID, o.Description, CASE WHEN (o.Status IS NULL) THEN 'new' WHEN (o.Status = 1) THEN 'confirmed' WHEN (o.Status = 3) THEN 'in production' WHEN (o.Status = 4) THEN 'ready' WHEN (o.Status = 5) THEN 'shipped' ELSE 'unknown status ''' || o.Status || '''' END FROM Orders o;

See also

IIF, NULLIF, COALESCE

The result datatype is determined by the following rules: Function: Specify the result data type of the result of a n aggregation over values of compatible data types, such as case expressions and columns at the same position in a union query expression. Syntax Rules: 1) Let DTS be the set of data types over which we m ust determine the final result data type. 2) All of the data types in DTS shall be comparable . 3) Case: a) If any of the data types in DTS is character s tring, then: 1) If any of the data types in DTS is variable- length character string, then the result data type is variable-length character string with maximum length in characters equal to the ma ximum of the lengths in characters and maximum lengths in characters of the data types in DTS. 2) Otherwise, the result data type is fixed-len gth character string with length in characters equal to the maxim um of the lengths in characters of the data types in DTS. 3) The characterset/collation is used from the first character string data type in DTS. b) If all of the data types in DTS are exact nume ric, then the result data

Page 72: Firebird 2.0 PSQL Reference Manual

type is exact numeric with scale equal to the maximum of the scales of the data types in DTS and the maximum precisio n of all data types in DTS. c) If any data type in DTS is approximate numeric , then each data type in DTS shall be numeric else an error is thrown. d) If some data type in DTS is a datetime data ty pe, then every data type in DTS shall be a datetime data type having the s ame datetime type. e) If any data type in DTS is BLOB, then each dat a type in DTS shall be BLOB and all with the same sub-type.

Page 73: Firebird 2.0 PSQL Reference Manual

NULLIF EXPRESSION

Purpose

Use NULLIF to more easily handle NULL values in a database.

Syntax

<psql_nullif> ::= NULLIF ( <psql_expr>, <psql_expr> )

Semantics

Returns NULL for a sub-expression if it has a specific value, otherwise returns the value of the subexpression.

NULLIF (V1, V2) is equivalent to the following case statement: CASE WHEN V1 = V2 THEN NULL ELSE V1 END

Example

UPDATE PRODUCTS SET STOCK = NULLIF(STOCK,0)

See also

IIF, COALESCE, IS IDENTICAL TO

Page 74: Firebird 2.0 PSQL Reference Manual

IIF EXPRESSION

Purpose

Use the IIF (“in-line IF”) expression to select one of two sub-expressions based on a condition.

Syntax

<psql_nullif> ::= IIF ( <psql_condition>, <psql_expression>, <psql _expression> )

Semantics

It returns the value of the first sub-expression if the given condition evaluates to TRUE, otherwise it returns a value of the second sub-expression.

IIF (<search_condition>, <value1>, <value2>) is a shorthand form for: CASE WHEN <search_condition> THEN <value1> ELSE <value2> END

Example

The below assignment statement places the absolute value of the variable 'val' into the variable 'abs_val':

abs_val = IIF( val<0, -val, val);

See also

NULLIF, COALESCE, IS IDENTICAL TO

Page 75: Firebird 2.0 PSQL Reference Manual

COALESCE EXPRESSION

Purpose

Use the coalesce expression to select the first non-NULL expression from a list.

Syntax

<psql_coalesce> ::= COALESCE ( <psql_expr_list> )

Semantics

Allows a column value to be calculated by a number of expressions, from which the first expression to return a non-NULL value is returned as the output value.

The coalesce function is a shorthand for the following case expressions:

• COALESCE (V1, V2) is equivalent to the following: CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END

• COALESCE (V1, V2,..., Vn) , for n >= 3, is equivalent to the following: CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, ...,Vn) END

Examples

UPDATE PRODUCTS SET STOCK = COALESCE(STOCK,0)

See also

IIF, NULLIF, IS IDENTICAL TO

Page 76: Firebird 2.0 PSQL Reference Manual

CAST EXPRESSION

Purpose

Use the CAST expression to convert an expression to another datatype.

Syntax

<psql_cast_expr> ::= CAST ( <psql_expr> AS <psql_datatype> )

Semantics

CAST() allows mixing of numerics and characters in a single expression by converting an expression to a specified datatype. Normally, only similar datatypes can be compared in search conditions. CAST() can be used in search conditions to translate one datatype into another for comparison purposes.

Examples

The first example shows how a text value can be cast to a date value. The second example shows how CAST can be used to declare the type of a parameter.

SELECT * FROM employees WHERE hire_date < CAST( '04/14/2006' AS DATE ); SELECT * FROM employees WHERE hire_date < CAST( ? AS DATE );

See also

Chapter 4, PSQL Datatypes

Page 77: Firebird 2.0 PSQL Reference Manual

SEQUENCE EXPRESSIONS

Purpose

Use a sequence expression to generate the next value from a sequence.

Syntax

<psql_sequence_expr> ::= GEN_ID ( <sequence_name>, <psql_expr> ) | NEXT VALUE FOR <sequence_name> <sequence_name> ::= <identifier>

Semantics

The GEN_ID() function:

• increments the current value of the specified sequence by the amount specified in its second argument

• returns the new value of the specified generator.

GEN_ID() is useful for automatically producing unique values that can be inserted into a UNIQUE or PRIMARY KEY column.

GEN_ID(<name>, 0) allows you to retrieve the current sequence value, but it should never be used in insert/update statements, as it produces a high risk of uniqueness violations in a concurrent environment.

Firebird 2.0 added the SQL-99 compliant NEXT VALUE FOR expression as a synonym for GEN_ID(<generator-name>, 1) .

Examples

The first example inserts a new employee into the employees table, adding the next available employee number from the the employee ID sequence. The second example initialises the employee ID sequence to the next available starting point from a master sequence, reserving 10,000 elements in the master sequence.

INSERT INTO employees VALUES ( 'Paul', NEXT VALUE F OR EMP_ID_SEQ ) SET SEQUENCE EMP_ID_SEQ TO GEN_ID(ID_SEQ, 10000)

See also

CREATE SEQUENCE

Page 78: Firebird 2.0 PSQL Reference Manual

SYSTEM INFORMATION FUNCTIONS

Purpose

Use the system information functions to retrieve information about the current state of the system.

Syntax

<psql_sys_info> ::= <current_user> | <current_role> | <current_connection> | <current_transaction> | <current_date> | <current_time> | <current_timestamp> | <gdscode> | <sqlcode> | <row_count>

Semantics

The system information functions return information about the current state of the system. There are five categories of system functions:

• The current user and current role functions return information about the security identity associated with the current connection.

• The current connection and current transaction functions return the system identifiers of the current connection and transaction, for amongst others logging and audit purposes.

• The date, time and timestamp functions return the current system date and time, aiding use of a single time standard across clients

• The gds and sql code functions return error information when used inside of exception handlers

• The row count function returns the number of rows affected by the last SQL statement on the current connection.

The system functions are documented individually on the next pages.

Examples

See the individual system function descriptions for usage examples.

See also

N/A

Page 79: Firebird 2.0 PSQL Reference Manual

CURRENT_USER, USER FUNCTION

Purpose

Use the current user functions to retrieve the name of the user associated with the current connection.

Syntax

<current_user> ::= USER | CURRENT_USER

Semantics

Use the current user functions to retrieve the name of the user associated with the current connection.

The return type of the CURRENT_USER and USER system functions is CHAR(31).

Examples

The below program block tests if the current user is SYSDBA, and if it is not throws a user-defined exception.

BEGIN IF CURRENT_USER != 'SYSDBA' THEN EXCEPTION NOT_AUTH 'Not authorised for this a ction'; END

See also

CURRENT_CONNECTION FUNCTION, CONTEXT VARIABLE FUNCTIONS

Page 80: Firebird 2.0 PSQL Reference Manual

CURRENT_ROLE FUNCTION

Purpose

Use the current role function to retrieve the name of the role associated with the current connection.

Syntax

<current_user> ::= CURRENT_ROLE

Semantics

Use the current role function to retrieve the name of the user associated with the current connection.

The return type of the CURRENT_ROLE system function is CHAR(31).

Examples

The below program block tests if the current role is ADMIN, and if it is not throws a user-defined exception.

BEGIN IF CURRENT_ROLE != 'ADMIN' THEN EXCEPTION NOT_AUTH 'Not authorised for this a ction'; END

See also

CURRENT_CONNECTION FUNCTION, CONTEXT VARIABLE FUNCTIONS

Page 81: Firebird 2.0 PSQL Reference Manual

CURRENT_CONNECTION FUNCTION

Purpose

Use the current connection system function to retrieve the system identifier of the current connection.

Syntax

<current_connection> ::= CURRENT_CONNECTION

Semantics

The CURRENT_CONNECTION system function returns the system identifier of the active connection. The return type is INTEGER.

Note: Because this value is stored on the database header page, it will be reset after a database restore.

Examples

The below example passes the current connection handle to a stored procedure.

EXECUTE PROCEDURE P_LOGIN(CURRENT_CONNECTION);

See also

CURRENT_TRANSACTION

Page 82: Firebird 2.0 PSQL Reference Manual

CURRENT_TRANSACTION FUNCTION

Purpose

Use the current transaction system function to retrieve the system identifier of the transaction connection.

Syntax

<current_connection> ::= CURRENT_TRANSACTION

Semantics

The CURRENT_TRANSACTION system function returns the system identifier of the active connection. The return type is INTEGER.

Note: Because this value is stored on the database header page, it will be reset after a database restore.

Examples

The below example logs the transaction handle in a log table:

CREATE TRIGGER LOGGER ON TABLE ACTION_LOG BEFORE INSERT AS BEGIN NEW.TXN_ID = CURRENT_TRANSACTION; END

See also

CURRENT_CONNECTION

Page 83: Firebird 2.0 PSQL Reference Manual

CURRENT_DATE FUNCTION

Purpose

Use the current date system function to retrieve the current system date,

Syntax

<current_date> ::= CURRENT_DATE

Semantics

The CURRENT_DATE system function returns the current system date, i.e. the date of the system that is running the Firebird server. There is no time zone associated with the current system date.

The return type of the CURRENT_DATE function is DATE.

Examples

The below examples calculates somebody's age in days by subtracting the birth date from the current date.

age_in_days = (CURRENT_DATE – birth_date);

See also

CURRENT_TIME, CURRENT_TIMESTAMP.

Page 84: Firebird 2.0 PSQL Reference Manual

CURRENT_TIME FUNCTION

Purpose

Use the current time system function to retrieve the current system time.

Syntax

<current_date> ::= CURRENT_TIME [ (<precision>) ] <precision> ::= { 0 ! 1 ! 2 ! 3 }

Semantics

The CURRENT_TIME system function returns the current system time, i.e. the time of the system that is running the Firebird server. There is no time zone associated with the current system time.

The optional precision parameter specifies the number of fractional digits in the seconds part of the returned time. The default is zero, i.e. time is rounded to a full second. The maximum precision is 3, which is rounding to a milli-second.

The return type of the CURRENT_TIME function is TIME.

Examples

The below examples calculates the time in seconds to excute a short loop:

DECLARE start AS TIME; DECLARE i AS INTEGER; DECLARE elapsed AS INTEGER; BEGIN i = 1000; start = CURRENT_TIME; WHILE (i>0) DO i = i – 1; elapsed = CURRENT_TIME – start; END

See also

CURRENT_DATE, CURRENT_TIMESTAMP.

Page 85: Firebird 2.0 PSQL Reference Manual

CURRENT_TIMESTAMP FUNCTION

Purpose

Use the current timestamp system function to retrieve the current system timestamp.

Syntax

<current_date> ::= CURRENT_TIMESTAMP [ (<precision>) ] <precision> ::= { 0 ! 1 ! 2 ! 3 }

Semantics

The CURRENT_TIMESTAMP system function returns the current system date and time, i.e. the date and time of the system that is running the Firebird server. There is no time zone associated with the current system timestamp.

The optional precision parameter specifies the number of fractional digits in the seconds part of the returned time. The maximum precision is 3, which is rounding to a milli-second. This is also the default precision.

The return type of the CURRENT_TIMESTAMP function is TIMESTAMP.

Examples

The below examples times a long loop with millisecond precision:

DECLARE start AS TIMESTAMP; DECLARE i AS INTEGER; DECLARE elapsed AS NUMERIC(9,3); BEGIN i = 100000; start = CURRENT_TIMESTAMP; WHILE (i>0) DO i = i – 1; elapsed = CURRENT_TIMESTAMP – start; END

See also

CURRENT_DATE, CURRENT_TIME

Page 86: Firebird 2.0 PSQL Reference Manual

GDSCODE FUNCTION

Purpose

Use the GDSCODE system function to retrieve the Firebird native error number of the current system exception, if any.

Syntax

<gdscode> ::= GDSCODE

Semantics

The GDSCODE system function returns an integer which is the numeric native error code for the active exception. It is available within the scope of a WHEN GDSCODE exception handling block. It will evaluate to zero elsewhere.

The GDSCODE variable returns a numeric representation of the GDS 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, the GDSCODE system function contain zero, regardless of the exception handling block type.

The return type of the GDSCODE system function is INTEGER.

Examples

The below example logs occurences of errors 335544349 and 335544350 into an error log table:

WHEN GDSCODE 335544349, GDSCODE 335544350 DO BEGIN INSERT INTO ERROR_LOG VALUES (GDSCODE); EXCEPTION; END

See also

SQLCODE, EXCEPTION HANDLERS

Page 87: Firebird 2.0 PSQL Reference Manual

SQLCODE FUNCTION

Purpose

Use the SQLCODE system function to retrieve the standardised SQL error number of the current system exception, if any.

Syntax

<gdscode> ::= SQLCODE

Semantics

The SQLCODE system function returns an integer which is the numeric SQL error code for the active exception. It is available within the scope of a WHEN SQLCODE or WHEN ANY exception handling block. It will evaluate to zero elsewhere.

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, the SQLCODE system function contain zero, regardless of the exception handling block type.

The return type of the SQLCODE system function is INTEGER.

Examples

The below example logs the SQL code of all errors into an error log table:

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

See also

GDSCODE, EXCEPTION HANDLERS

Page 88: Firebird 2.0 PSQL Reference Manual

ROW_COUNT FUNCTION

Purpose

Use the ROW_COUNT system function to retrieve the number of rows affected by the last SQL statement.

Syntax

<row_count> ::= ROW_COUNT

Semantics

The ROW_COUNT system function returns the number of rows affected by the last SQL statement on the current connection. If used within a SELECT statement, it returns the number of rows returned so far.

The return type of the ROW_COUNT system function is INTEGER.

Examples

The first example tries to update a table. If the record is not found, a new record is inserted instead. The second example keeps a running total of the number of rows returned.

UPDATE TABLE1 SET FIELD1 = 0 WHERE ID = :ID; IF (ROW_COUNT = 0) THEN INSERT INTO TABLE1 (ID, FIELD1) VALUES (:ID, 0); SELECT ROW_COUNT, RDB$RELATION_NAME FROM RDB$RELATIONS;

See also

N/A

Overview of PSQL conditions

PSQL has a rich set of conditional tests to control program flow in a PSQL routine, for example through the IF THEN ELSE or WHILE DO statements. In general, the conditional constructs in PSQL exactly match the constructs available in the WHERE clause in SQL statements.

Syntax

<psql_condition> ::= <psql_simple_condition> | NOT <psql_condition> | ( <psql_condition> ) | ( <psql_and_condition> | ( <psql_or_condition> <psql_simple_condition ::= <sql_predicate> | <trigger_predicate> <sql_predicate> ::= <comparison_predicate> | <quantified_predicate> | <null_predicate> | <between_predicate> | <in_predicate>

Page 89: Firebird 2.0 PSQL Reference Manual

| <like_predicate> | <starting_predicate> | <containing_predicate> | <exists_predicate> | <unique_predicate> <trigger_predicate> ::= INSERTING | UPDATING | DELETING

Note: Trigger predicates are only valid inside the body of trigger definitions. Using trigger predicates in a procedure definition will cause a syntax error. See the chapter on working with triggers for more information about tigger predicates.

Semantics

Precedence is the order in which Firebird evaluates different conditions in the same expression. When evaluating an expression containing multiple conditions, Firebird evaluates conditions with higher precedence before evaluating those with lower precedence. Conditions with equal precedence are evaluated from left to right within an expression.

The below table lists the levels of precedence among SQL condition from high to low. Conditions listed in the same row have the same precedence. As the table indicates, expression are evaluated operators before conditions.

Element Defining keywords

expression operators Expression operators (+, - , etc.) are evaluated before all condition operators.

trigger_predicate INSERTING, UPDATING, DELETING

comparison predicate, quantified_predicate

=, |=, <, >, <=, >=; possibly in combination with ALL, SOME or ANY

between_predicate, like_predicate, in_predicate, null_predicate, exists_predicate, containing_predicate, starting_predicate, unique_predicate

IS [NOT] NULL, [NOT] LIKE, CONTAINING, STARTING, [NOT] BETWEEN, [NOT] IN, EXISTS, UNIQUE

negation NOT

and_condition AND

or_condition OR

Page 90: Firebird 2.0 PSQL Reference Manual

Element Defining keywords

Examples

The following code snippet tests both if variable A is larger than 23 and that table RDB$DATABASE has exactly one row:

A>23 AND SINGULAR(SELECT * FROM RDB$DATABASE)

See also

IF THEN ELSE, WHILE DO

Page 91: Firebird 2.0 PSQL Reference Manual

AND CONDITION

Pupose

Use the AND condition clause to test if two conditions are met simultaneously.

Syntax

<psql_unique_clause ::= <psql_condition> AND <psql_condition>

Semantics

The AND condition tests if two subconditions are true at the same time. If either subcondition evaluates to NULL, then the AND condition evaluates to NULL as well. This is known as 'tri-state logic'. The below truth table shows the result of applying AND to two conditions:

AND True False Null

True True False Null

False False False False

Null Null False Null

The AND condition uses “shortcut evaluation”: if the left hand condition is FALSE, the result is FALSE and the right hand side is not evaluated at all.

Examples

The following code snippet will never generate a division-by-zero exception, even if variable 'a' equals zero:

IF ( A!=0 AND (5/A)>3 ) THEN EXCEPTION DIV_BY_ZERO;

See also

OR CONDITION

Page 92: Firebird 2.0 PSQL Reference Manual

OR CONDITION

Pupose

Use the OR condition clause to test if either of two conditions are met.

Syntax

<psql_unique_clause ::= <psql_condition> OR <psql_condition>

Semantics

The OR condition tests if either of two subconditions are true. If either subcondition evaluates to NULL, then the OR condition evaluates to NULL as well. This is known as 'tri-state logic'. The below truth table shows the result of applying OR to two conditions:

OR True False Null

True True True True

False True False Null

Null True Null Null

The AND condition uses “shortcut evaluation”: if the left hand condition is TRUE, the result is TRUE and the right hand side is not evaluated at all.

Examples

The following code snippet will never generate a division-by-zero exception, even if variable 'a' equals zero:

IF ( A=0 OR (5/A)>3 ) THEN EXCEPTION OUT_OF_RANGE;

See also

AND CONDITION

Page 93: Firebird 2.0 PSQL Reference Manual

SCALAR COMPARISON CONDITION

Pupose

Use the scalar comparison operators to compare two numerical or text expressions.

Syntax

<comparison_predicate> ::= <psql_expr> <compare_op> <psql_expr> <compare_op> ::= = | < | > | <= | !> | >= | !< | <> | !=

Semantics

The comparison operators compare two values and tests for a certain relationship between the two. The test performed is specified in the below table.

Operator Tests for

= Equality

<>, != Inequality

< Less than

> Greater then

<=, !> Not greater than

>=, !< Not less than

If either of the two expressions evaluates to NULL, than the result of the the test is also NULL. This also means that the (in-)equality operator cannot be used to test for NULL-ness, use the IS NULL operator instead.

The two expressions should normally be of the same type. If the types differ, the types are automatically cast to types that can be compared:

• integer and scaled result in a scaled comparison

• integer/scaled and float result in a comparison of floats

• numeric and date/time results in a comparison of timestamps

• text and non-text results in a comparison of texts; a date string counts as date, not text.

Examples

The following are examples of valid comparisons:

a <> 23 birth_day <= 'today'

Page 94: Firebird 2.0 PSQL Reference Manual

name = 'John Smith'

See also

IF NULL, Group Comparison Conditions

Page 95: Firebird 2.0 PSQL Reference Manual

GROUP COMPARISON CONDITION

Pupose

Use the group comparison operators to compare a single value with the result set of a single column query.

Syntax

<psql_quantified_clause> ::= <psql_expr> <compare_op> <group_op> <select_stmt> <compare_op> ::= = | < | > | <= | !> | >= | !< | <> | != <group_op> ::= ALL | { ANY ! SOME }

Note: The select statement must have exactly one item in its select list, i.e. The result set must exist of exactly one column.

Semantics

The group comparison operators compare a value with the entire result set of a single column query and tests for a certain relationship between the value and each row of the result set. If the ALL keyword is specified, then every row must pass the test for the group to pass the test. If the ANY or the SOME keyword is specified, then only at least one row must pass the test for the group to pass the test.

The test performed is specified in the below table.

Operator Tests for

= Equality

<>, != Inequality

< Less than

> Greater then

<=, !> Not greater than

>=, !< Not less than

If the left hand expression evaluates to NULL, than the result of the the test is also NULL. If the result set of the subquery has zero rows then the result of the test is also NULL.

The two expressions should normally be of the same type. If the types differ, the types are automatically cast to types that can be compared:

Page 96: Firebird 2.0 PSQL Reference Manual

• integer and scaled result in a scaled comparison

• integer/scaled and float result in a comparison of floats

• numeric and date/time results in a comparison of timestamps

• text and non-text results in a comparison of texts; a date string counts as date, not text.

Examples

The following are examples of valid group comparison statements:

a < ANY (SELECT col_a FROM mytable) b = ALL (SELECT col_b FROM mystable WHERE col_b= :b)

See also

Scalar Comparison Conditions

Page 97: Firebird 2.0 PSQL Reference Manual

IS NULL CONDITION

Pupose

Use the IS NULL predicate to test if a value is NULL or not NULL.

Syntax

<null_predicate ::= <psql_expr> IS [NOT] NULL

Semantics

To test for nulls, use only the comparison conditions IS NULL and IS NOT NULL. If you use any other condition with nulls and the result depends on the value of the null, then the result is NULL. Because null represents a lack of data, a null cannot be equal or unequal to any value or to another null.

Examples

At the end of the following routine variable 'a' will have value 4, not value 3:

DECLARE a INTEGER; BEGIN IF (a=NULL) THEN a = 3; IF (a IS NULL) THEN a = 4; END

See also

IS DISTINCT FROM

Page 98: Firebird 2.0 PSQL Reference Manual

IS DISTINCT FROM CONDITION

Pupose

Use the IS DISTINCT FROM predicate to test if a value is identical to another value.

Syntax

<null_predicate ::= <psql_expr> IS [NOT] DISTINCT FROM <psql_expr>

Semantics

The IS DISTINCT FROM tests if two values are identical, either because both are known (i.e. not NULL) and the same, or because both are unknown.

Examples

At the end of the following routine variable 'a' will have value 3, not value 4:

DECLARE a INTEGER; BEGIN IF (a IS NOT DISTINCT FROM NULL) THEN a = 3; IF (a IS DISTINCT FROM 3) THEN a = 4; IF (a IS NULL) THEN a = 4; END

See also

IS NULL

Page 99: Firebird 2.0 PSQL Reference Manual

BETWEEN CONDITION

Pupose

Use the BETWEEN predicate to test if a value is within a certain range.

Syntax

<between_predicate> ::= <psql_expr> BETWEEN <psql_expr> AND <psql_expr > | <psql_expr> NOT BETWEEN <psql_expr> AND <psql_ expr>

Semantics

The BETWEEN predicate test if a value lies in certain range, inclusive of the limits of the range. The following two conditions are logically equivalent:

a BETWEEN b AND c

a >= b AND a<=c

And the following two conditions are also logically equivalent:

a NOT BETWEEN b AND c

a <b OR a>c

If any of the three expressions in a [NOT] BETWEEN condition is NULL, then the entire condition evaluates to NULL.

The three expressions should normally be of the same type. If the types differ, the types are automatically casted to types that can be compared. The rules for this are the same as for scalar comparisons.

Examples

The below are examples of valid BETWEEN predicates:

a BETWEEN 23 AND 46 order_date NOT BETWEEN DATE 'today' AND DATE 'to day'-366

See also

Scalar Comparison Conditions

Page 100: Firebird 2.0 PSQL Reference Manual

IN CONDITION

Pupose

Use the IN predicate to test if a value is within a group of values. The group can either be a list of values or the result set of a single column query.

Syntax

<in_predicate> ::= <psql_expr> [NOT] IN ( psql_expr_list ) | <psql_expr> [NOT] IN ( select_stmt )

Semantics

The IN predicate tests for membership of a value in a list of values or a result set of values:

• IN is equivalent with the = ANY group comaprison

• NOT in is equivalent with != ALL group comparison

If any item in the list following a NOT IN operation evaluates to null, then the entire condition evaluates to NULL. This is because the condition is internally calculated as a series of AND conditions, which cannot be short-cut evaluated.

Examples

The following are valid examples of IN usage:

disciple IN ('John', 'Paul') rank NOT IN (1, 2, 3)

The following statement returns no rows:

SELECT ’True’ FROM employees WHERE department_id NOT IN (10, 20, NULL);

The preceding example returns no rows because the WHERE clause condition evaluates to: department_id != 10 AND department_id != 20 AND department_id != NULL. Because the third condition compares department_id with a NULL, it results in a NULL, so the entire expression results in NULL. This behavior can easily be overlooked, especially when the NOT IN operator references a subquery.

See also

Group Comparison Conditions

Page 101: Firebird 2.0 PSQL Reference Manual

LIKE CONDITION

Pupose

Use the LIKE predicate to test a text value for similarity to a specified text pattern.

Syntax

<like_predicate> ::= <match> LIKE <pattern> [ ESCAPE <escape> ] | <match> NOT LIKE <pattern> [ ESCAPE <escape> ] <match> ::= <psql_expr> <pattern> ::= <psql_expr> <escape> ::= <psql_expr>

Element Description

match An expression evaluating to text

pattern An expression evaluating to text

escape An expression evaluating to a single character text

Semantics

The LIKE condition specifies a test involving pattern matching. Whereas the

equality operator (=) exactly matches one character value to another, the LIKE conditions match a portion of one character value to another by searching the first value for the pattern specified by the second.

LIKE compares strings using characters as defined by the input character set and matching is case sensitive.

If the escape clause is ommitted, then there is no default escape character. If any of the three expressions is NULL, then the result is NULL. The escape character, if specified, must be a character string of length 1.

The pattern can contain the special pattern-matching characters:

• '%' matches any string of any length (including length 0)

• '_' matches any single character.

To search for the characters '%' and '_', precede them by the escape character. For example, if the escape character is '@', then you can use '@%' to search for '%', and '@_' to search for '_'.

To search for the escape character, repeat it. For example, if '@' is the escape character, then you can use '@@' to search for '@'. In the pattern, the escape character should be followed by one of '%', '_', or the escape character itself. The escape character cannot be '%' or '_'.

In Firebird, LIKE conditions used in SQL statement WHERE conditions are not index optimised, and the variant form STARTING WITH exists. In PSQL, where we work with scalar values, there is no performance differnce betweeb LIKE and STARTING WITH.

Page 102: Firebird 2.0 PSQL Reference Manual

Examples

The below are examples of valid LIKE expressions. The third example finds all names that contain the string 'A_B':

last_name LIKE 'Ma%' last_name LIKE 'Smith_' last_name LIKE '%A\_B%' ESCAPE '\'

See also

CONTAINING, STARTING WITH

Page 103: Firebird 2.0 PSQL Reference Manual

CONTAINING CONDITION

Pupose

Use the CONTAINING predicate to test if a text value is contained in another text value.

Syntax

<containing_predicate ::= <psql_match> [ NOT ] CONTAINING <psql_pattern> <match> ::= <psql_expr> <pattern> ::= <psql_expr>

Element Description

match An expression evaluating to text

pattern An expression evaluating to text

Semantics

The CONTAINING condition search a text for a sequence of characters equal to the pattern. The search is case insensitive, i.e. the pattern 'Peter' matches all of 'peter', 'Peter', 'PETER', 'PeTeR', etc.

If match evaluates to a non-text value, it is cast to the text equivalent and the result is used in the search.

Examples

The below are examples of valid CONTAINING conditions:

last_name CONTAINING 'a_b' last_name CONTAINING 'Smith' hire_date CONTAINING '1998'

See also

LIKE Condition, STARTING WITH Condition

Page 104: Firebird 2.0 PSQL Reference Manual

STARTING WITH CONDITION

Pupose

Use the STARTING WITH predicate to test if a text value starts with a certain text value.

Syntax

<starting_predicate ::= <psql_match> [ NOT ] STARTING [ WITH ] <psql_pat tern> <match> ::= <psql_expr> <pattern> ::= <psql_expr>

Element Description

match An expression evaluating to text

pattern An expression evaluating to text

Semantics

The STARTING WITH condition specifies a test involving a search for text starting with the pattern string. STARTING WITH 'text' is equivalent to LIKE 'text%'.

STARTING WITH compares strings using characters as defined by the input character set and matching is case sensitive.

Examples

The following are examples of valid use of STARTING WITH:

last_name STARTING WITH 'Smi' last_name STARTING 'Smi' last_name NOT STARTING WITH 'Smi'

See also

LIKE Condition, CONTAINING Condition

Page 105: Firebird 2.0 PSQL Reference Manual

EXISTS CONDITION

Pupose

Use the EXISTS predicate to test if a query has a result set with at least one row.

Syntax

<exists_predicate> ::= EXISTS ( <select_stmt> ) | NOT EXISTS ( <select_stmt> )

Element Description

select_stmt A SELECT statement as defined in the SQL Reference Manual

Semantics

The EXISTS condition is a fast way of testing if a certain row exists. The similar test (SELECT COUNT(*) FROM ...) >0 is by comparison far more expensive, because all rows must be traversed in order to get to an accurate count.

Examples

The below are examples of valid use of the EXISTS condtion. Both examples return FALSE:

EXISTS( SELECT * FROM rdb$database WHERE 1=0 ) NOT EXISTS( SELECT * FROM rdb$relations )

See also

SINGULAR Condition

Page 106: Firebird 2.0 PSQL Reference Manual

SINGULAR CONDITION

Pupose

Use the SINGULAR predicate to test if the result set of a query has exactly one result row.

Syntax

<unique_predicate ::= SINGULAR ( <select_stmt> ) | NOT SINGULAR ( <select_stmt> )

Element Description

select_stmt A SELECT statement as defined in the SQL Reference Manual

Semantics

The SINGULAR condition tests if the result set of the select statement has exactly one result row. Firebird traverses the result set until the end is reached or until two result rows are found. On a large base table where there is likely to be one result, it hence can be an expensive operation, because all rows must be traversed in order to get to an accurate count.

Examples

The below are examples of valid use of the SINGULAR condtion. Both examples return TRUE:

SINGULAR( SELECT * FROM rdb$database ) NOT SINGULAR( SELECT * FROM rdb$relations )

See also

EXISTS Condition

Overview of PSQL Statements

PSQL has a full set of statements, blending the best from traditional procedural languages like C or Pascal and from the SQL relational language:

• From standard procedural languages: variable assignment, calling functions and procedures, flow control through IF THEN ELSE, WHILE DO and BREAK, structured exception handling, with throw and catch

• From the SQL language: embedded forms of SELECT, INSERT, UPDATE and DELETE; excution of SQL statements dynamically created at runtime

• And to top it of: high performance cursor processing, for cursors originating from a SELECT query and for cursors originating from a selectable stored procedure.

Because PSQL programs run on the server, data transfer between the relational core and the PSQL engine is very fast, much faster than transfer to a client application.

Syntax overview

<psql_statement> ::= assignment_stmt

Page 107: Firebird 2.0 PSQL Reference Manual

| close_stmt | compound_stmt | psql_delete_stmt | exception_stmt | fetch_stmt | raise_stmt | exec_procedure_stmt | exec_sql_stmt | exit_stmt | for_exec_into_stmt | for_select_stmt | if_then_else_stmt | psql_insert_stmt | leave_stmt | open_stmt | post_event_stmt | psql_select_stmt | psql_update_stmt | while_stmt | suspend_stmt

Page 108: Firebird 2.0 PSQL Reference Manual

ASSIGNMENT STATEMENT

Pupose

Use the assignment statement: to assign the value of expression to variable, a local variable, input parameter, output parameter, or – in the case of a trigger – a context variable.

Syntax

<assignment_stmt> ::= <identifier> = <psql_expression>;

Element Description

identifier Name of a variable or parameter

psql_expression Expression with a datatype matching the variable

Semantics

An assignment statement sets the value of a local variable, input parameter, or output parameter. Variables must be declared before they can be used in assignment statements.

Examples

i = i + 23; lbl = 'Sales by state';

See also

VARIABLE DECLARATIONS

Page 109: Firebird 2.0 PSQL Reference Manual

COMPOUND STATEMENT

Pupose

Use a compound statement to defines a block of statements that executes as one.

Syntax

<compound_stmt> ::= BEGIN <stmt_list> [ <excep_handlers> ] END <stmt_list> ::= <psql_statement> | <psql_statement> <stmt_list>

Note: unlike all other PSQL statements, a BEGIN .. END block is not followed by a semicolon.

Element Description

excep_handlers Optional exception handlers for the block

psql_statement A single PSQL statement; see the STATEMENTS sections for an overview of statement types.

Semantics

Each block of statements in the procedure body starts with a BEGIN statement and ends with an END statement. A compound statement can itself contain other compound statements, so there may be many levels of nesting.

A compound statement can have its own error handlers. See the section on exception handlers for information about how exceptions are handled.

Examples

The below is an example of a valid block:

BEGIN a = 10 / b; WHEN GDSCODE arith_except DO a = 0; END

See also

PSQL Programs

Page 110: Firebird 2.0 PSQL Reference Manual

DELETE STATEMENT

Pupose

Use the delete statement to delete a number of rows from a table. The PSQL delete statement is identical to the SQL delete statement followed by a semicolon.

Syntax

<psql_delete_stmt> ::= <delete_stmt> ;

Element Description

delete_statement A SQL delete statement as defined in the SQL Reference manual.

Semantics

See the SQL Reference Manual for a description of the delete statement.

Examples

The below is an example of a valid DELETE statement in PSQL:

DELETE FROM table1 WHERE id = :emp_id

See also

INSERT, UPDATE and SELECT

Page 111: Firebird 2.0 PSQL Reference Manual

EXCEPTION STATEMENT

Pupose

Use this statement to raise a named exception or re-raise an active exception from within an exception handler.

Syntax

<exception_stmt> ::= EXCEPTION <exception_name>; | EXCEPTION <exception_name> <psql_expr>; | EXCEPTION; <exception_name> ::= <identifier>

Element Description

identifier Name of a defined exception.

psql_expr Text expression, overriding the predefined associated message for the named exception.

Semantics

Raises the named exception: an exception is a user-defined error that returns an error message to the calling application unless handled by a WHEN statement.

The third syntax form – EXCEPTION without an exception name - re-raises the current exception is only valid from within an exception handler. It has no effect when used in the statement part of a block.

Examples

The below examples show valid uses of the EXCEPTION statement:

EXCEPTION bad_data_found; EXCEPTION user_error 'Value must be smaller than 10 0'; WHEN ANY IF SQLCODE <> -802 THEN EXCEPTION;

See also

EXCEPTION HANDLERS

Page 112: Firebird 2.0 PSQL Reference Manual

EXECUTE PROCEDURE STATEMENT

Pupose

Executes a stored procedure with the listed input arguments, returning values in the listed output arguments following RETURNING_VALUES.

Syntax

<exec_procedure_stmt> ::= EXECUTE PROCEDURE <proc_name> [ <input_params> | ( <input_params> ) ] [ RETURNING_VALUES [ <var_list> | ( <var_list> ) ]] ; <input_params> ::= <psql_expr_list> <var_list> ::= <variable_name> | <variable_name> , <var_list> <variable_name> ::= <identifier>

Element Description

psql_expr_list A comma separated list of PSQL expressions; see the EXPRESSIONS section for a detailed discussion.

variable_name The name of a local variable of the enclosing body or of a parameter of the enclosing procedure definition.

Semantics

EXECUTE PROCEDURE calls the specified stored procedure. If the procedure requires input parameters, the number of expressions passed in must match the number of formal parameters. Expressions are always passed by value, i.e. The called procedure works with local copies of the values passed in.

If a procedure returns output parameters to a PSQL routine, receiving variables must be supplied in the RETURNING_VALUES clause to hold the values returned. The variables can be either local variables or in the case of a procedure body, parameters of the defining procedure.

A stored procedure can itself execute a stored procedure. Each time a stored procedure calls another procedure, the call is said to be nested because it occurs in the context of a previous and still active call to the first procedure.

Stored procedures can be nested up to 1,000 levels deep. This limitation helps to prevent infinite loops that can occur when a recursive procedure provides no absolute terminating condition. Nested procedure calls may be restricted to fewer than 1,000 levels by memory and stack limitations of the server.

Examples

The below examples show valid uses of the EXECUTE PROCEDURE statement:

EXECUTE PROCEDURE log_error('SYS2307', 'No such employee'); EXECUTE PROCEDURE fac( 23 ) RETURNING_VALUES :fa ctorial;

Page 113: Firebird 2.0 PSQL Reference Manual

See also

DEFINING PROCEDURES

Page 114: Firebird 2.0 PSQL Reference Manual

EXECUTE SQL STATEMENT

Pupose

The execute sql statement allows the excution of a – possibly dynamically created - SQL statement, contained in a string expression.

Syntax

<exec_sql_stmt> ::= EXECUTE STATEMENT <psql_expr> [ INTO <var_list> ] ; <var_list> ::= <variable_name> | <variable_name> , <var_list> <variable_name> ::= <identifier>

Element Description

psql_expr A PSQL expression evaluating to a string containing a valid SQL statement.

variable_name The name of a local variable of the enclosing body or of a parameter of the enclosing procedure definition.

Semantics

The execute SQL statement allows the execution of SQL statements that are not also PSQL statements (i.e. SELECT, INSERT, DELETE and UPDATE), for example a SET STATISTICS statement. It also allows the excution of dynamically constructed SQL statements.

Note that not all SQL statements are allowed. Statements that alter the state of the current transaction (such as COMMIT and ROLLBACK) are not allowed and will cause a runtime error.

The INTO clause is only meaningful if the SQL statement returns values, such as SELECT, INSERT ... RETURNING or UPDATE ... RETURNING. If the SQL statement is a SELECT statement, it must be a 'singleton' SELECT, i.e. it must return exactly one row. To work with SELECT statements that return multiple rows, use the FOR EXECUTE INTO statement.

It is not possible to use parameter markers ('?') in the SQL statement, as there is no way to specify the input actuals. Rather than using parameter markers, dynamically construct the SQL statement, using the input actuals as part of the construction process.

Examples

The below examples show valid uses of the EXECUTE STATEMENT statement:

EXECUTE STATEMENT 'SET STATISTICS INDEX emp_id_i dx'; EXECUTE STATEMENT 'SELECT 3 FROM rdb$database' I NTO :a;

See also

Page 115: Firebird 2.0 PSQL Reference Manual

FOR EXECUTE INTO, and the PSQL statements SELECT, UPDATE, INSERT and DELETE for using SQL directly in your PSQL routine. See the SQL Reference Manual for a full discussion of SQL statements.

Page 116: Firebird 2.0 PSQL Reference Manual

EXIT STATEMENT

Pupose

Use EXIT to terminate a PSQL routine from any place in its code.

Syntax

<exit_stmt> ::= EXIT ;

Semantics

The EXIT statement jumps to the final END statement in the PSQL body, at wich time the usual clean up actions occur. See the Procedure/Trigger Body section for a discussion of these actions.

EXIT is most commonly used inside a complex routine to signal the end of a code path. Using EXIT usually allows for easier to read code in such circumstances.

Examples

The below example shows a loop that potentially has a thousand itterations. After itteration 13 the loop is terminated and the PSQL program finishes.

DECLARE i INTEGER; BEGIN WHILE (i<1000) DO BEGIN i = i + 1; IF (i=13) THEN EXIT; END END;

See also

LEAVE statement

Page 117: Firebird 2.0 PSQL Reference Manual

FETCH CURSOR STATEMENT

Pupose

Use the FETCH statement to open a local cursor.

Syntax

<open_stmt> ::= FETCH <cursor_name> INTO <var_list>; <cursor_name> ::= <identifier> <var_list> ::= <variable_name> | <variable_name> , <var_list> <variable_name> ::= <identifier>

Element Description

cursor_name Name of a local cursor

variable_name The name of a local variable or of a parameter of the enclosing procedure definition.

Semantics

The FETCH statement retrieves a row of the cursor result set into local variables for further processing. The cursor must have been declared in the declarations section of the PSQL program, and previously opened with an OPEN statement.

Fetching rows beyond the last row will not raise a NOT_FOUND exception, but is silently ignored. Use the ROW_COUNT function to test if values were returned from the result set.

Attempts to fetch from a cursor that is closed, or attempts to fetch from a named FOR SELECT cursor will fail and generate a run-time exception.

Examples

The following PSQL program opens a cursor, fetches all rows and then closes the cursor:

DECLARE SYS_TAB_CNT INTEGER = 0; DECLARE FLAG INTEGER; DECLARE C CURSOR FOR (SELECT COALESCE(RDB$SYSTEM_FLAG, 0) FROM RDB$RE LATIONS ); BEGIN OPEN C; WHILE (1 = 1) DO BEGIN FETCH C INTO :FLAG; IF (ROW_COUNT = 0) THEN LEAVE; IF (FLAG=1) THEN SYS_TAB_CNT = SYS_TAB_CNT + 1 END CLOSE C; END

See also

Page 118: Firebird 2.0 PSQL Reference Manual

OPEN statement, CLOSE statement, FOR SELECT statement.

Page 119: Firebird 2.0 PSQL Reference Manual

FOR EXECUTE INTO STATEMENT

Pupose

Use the FOR EXECUTE INTO statement to execute a – possibly dynamically created – SELECT statement contained in a string and process all its result rows.

Syntax

<for_exec_stmt> ::= [ <label> : ] FOR EXECUTE <psql_expr> INTO <var_list> DO <psql_statement> <label> ::= <identifier> <var_list> ::= <variable_name> | <variable_name> , <var_list> <variable_name> ::= <identifier>

Element Description

label A label naming the loop

psql_expr A PSQL expression evaluating to a string containing a valid SQL statement.

psql_statement A PSQL statement. Typically this will be a compund statement.

variable_name The name of a local variable of the enclosing body or of a parameter of the enclosing procedure definition.

Semantics

The execute SQL statement allows the execution of dynamically constructed SELECT statements. The rows of the result set are sequentially assigned to the variables specified in the INTO clause, and for each row the statement in the DO clause is executed.

To work with SELECT statements that return only a single row, consider using the EXECUTE INTO statement.

It is not possible to use parameter markers ('?') in the SELECT statement, as there is no way to specify the input actuals. Rather than using parameter markers, dynamically construct the SELECT statement, using the input actuals as part of the construction process.

Examples

The below examples shows a valid use of the FOR EXECUTE statement:

FOR EXECUTE 'SELECT ROW_COUNT FROM rdb$relations ' INTO :i DO BEGIN INSERT INTO my_log VALUES( :i ); END

See also

Page 120: Firebird 2.0 PSQL Reference Manual

EXECUTE INTO statement, SELECT INTO statement, BREAK statement. See the SQL Reference Manual for a full discussion of SQL statements.

Page 121: Firebird 2.0 PSQL Reference Manual

FOR SELECT DO STATEMENT

Pupose

Repeats the statement or block following DO for every row retrieved by the select statement.

Syntax

<for_select_stmt> ::= [ <label> : ] FOR <select_stmt> INTO <var_list> [ AS CURSOR <cursor_name> ] DO <psql_statement> <label> ::= <identifier> cursor_name ::= <identifier> <var_list> ::= <variable_name> | <variable_name> , <var_list> <variable_name> ::= <identifier>

Element Description

label A label naming the loop

select_stmt A regular SQL select statement. See the SQL Reference manual for details about this element.

psql_statement A PSQL statement. Typically this body will be a compound statement.

cursor_name The name of a local variable of the enclosing body or of a parameter of the enclosing procedure definition.

variable_name The name of a local variable of the enclosing body or of a parameter of the enclosing procedure definition.

Semantics

The FOR SELECT DO statement allows the compact processing of a SELECT statement. The rows of the result set are sequentially assigned to the variables specified in the INTO clause, and for each row the statement in the DO clause is executed.

If the AS CURSOR clause is present, the select statement is assigned a cursor name. The current row being processed by the FOR SELECT DO statement can be referred to in DELETE and UPDATE statements in the body of the FOR SELECT DO by using the WHERE CURRENT OF clause of those statements.

Examples

In the below example, the code considers each row contained in table 'mytable' and proceeds to delete those rows where col1 is equal to 23:

DECLARE a INTEGER; BEGIN FOR SELECT col1 FROM mytable INTO :a CURSOR del_ list DO BEGIN IF (a=23) THEN

Page 122: Firebird 2.0 PSQL Reference Manual

DELETE FROM mytable WHERE CURRENT OF del_l ist; END END;

See also

Refer to the SQL Reference Manual for details about the SELECT statement and about using the WHERE CURRENT OF syntax.

Page 123: Firebird 2.0 PSQL Reference Manual

IF THEN ELSE STATEMENT

Pupose

Tests a condition, and if it evaluates to TRUE performs the statement or block following THEN; otherwise, it performs the statement or block following ELSE, if present.

Syntax

<if_then_else_stmt> ::= IF <psql_condition> THEN <psql_statement> [ ELSE <psql_statement> ]

Element Description

psql_condition A PSQL condition. See the section on Conditions for more information.

psql_statement A PSQL statement. Often this will be a compound statement.

Semantics

The condition is evaluated and if it evaluates to TRUE the statement in the THEN clause is executed. If it is not TRUE, i.e. It evaluates to FALSE or to NULL, and an ELSE clause is present, then the statement in the ELSE clause is executed.

IF statements can be nested, i.e. The statements in the THEN or ELSE clauses can be IF statements also. If the THEN clause contains a IF THEN ELSE statement, then that ELSE clause is deemed to be part of the nested IF, just as in nearly all other programming languages. Enclose the nested if in a compound statement if you want the ELSE clause to refer to the enclosing IF statement.

Examples

The below examples show valid uses of the IF statement:

IF (a>23) THEN a = a – 1; IF (myname='Paul') THEN a = a + 1; ELSE a = i;

See also

WHEN DO statement

Page 124: Firebird 2.0 PSQL Reference Manual

INSERT STATEMENT

Pupose

Use the INSERT statement to insert new rows into a table. The PSQL insert statement is identical to the SQL insert statement followed by a semicolon.

Syntax

<psql_insert_stmt> ::= <insert_stmt> ;

Element Description

insert_stmt A SQL insert statement as defined in the SQL Reference manual.

Semantics

See the SQL Reference Manual for a description of the insert statement.

Examples

The below is an example of a valid INSERT statement in PSQL:

INSERT INTO table1 VALUES ( :emp_id );

See also

DELETE, UPDATE and SELECT

Page 125: Firebird 2.0 PSQL Reference Manual

LEAVE (BREAK) STATEMENT

Pupose

Use the LEAVE statement to force an exit from a looping construct.

Syntax

<break_stmt> ::= { BREAK ! LEAVE } [ <label> ] ;

Semantics

The LEAVE statement terminates the flow in a loop, causing flow of control to move to the statement following the END statement that completes that loop. It is available inside of WHILE, FOR SELECT and FOR EXECUTE statements only, otherwise a syntax error will be thrown.

The LEAVE <label> syntax allows PSQL loops to be marked with labels and terminated in Java style. The purpose is to stop execution of the current block and unwind back to the specified label. After that execution resumes at the statement following the terminated loop. Note that LEAVE without an explicit label means interrupting the current (most inner) loop.

The SQL-99 standard keyword LEAVE deprecates the existing BREAK, so in new code the use of LEAVE is preferred.

Examples

The following example shows how the LEAVE statement can be used to force an exit to a FOR SELECT loop in the middle of processing the result set:

FOR SELECT COALESCE(RDB$SYSTEM_FLAG, 0), RDB$RELATION_NAME FROM RDB$RELATIONS ORDER BY 1 INTO :RTYPE, :RNAME DO BEGIN IF (RTYPE = 0) THEN SUSPEND; ELSE LEAVE; -- exits current loop END

The following trivial example shows how a named WHILE loop can be aborted:

CNT = 100; L1: WHILE (CNT >= 0) DO BEGIN IF (CNT < 50) THEN LEAVE L1; -- exists WHILE loop CNT = CNT – l; END

The last example shows how LEAVE may be used to exit nested loops:

STMT1 = 'SELECT RDB$RELATION_NAME FROM RDB$RELATIONS'; L1: FOR EXECUTE STATEMENT :STMT1 INTO :RNAME DO

Page 126: Firebird 2.0 PSQL Reference Manual

BEGIN STMT2 = 'SELECT RDB$FIELD_NAME FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = '; L2: FOR EXECUTE STATEMENT :STMT2 || :RNAME INTO : FNAME DO BEGIN IF (RNAME = 'RDB$DATABASE') THEN LEAVE L1; -- exits the outer loop ELSE IF (RNAME = 'RDB$RELATIONS') THEN LEAVE L2; -- exits the inner loop ELSE SUSPEND; END END

See also

WHILE DO statement, FOR SELECT DO statement, FOR EXECUTE DO statement.

Page 127: Firebird 2.0 PSQL Reference Manual

OPEN CURSOR STATEMENT

Pupose

Use the OPEN statement to open a local cursor.

Syntax

<open_stmt> ::= OPEN <cursor_name>; <cursor_name> ::= <identifier>

Element Description

cursor_name Name of a local cursor

Semantics

The OPEN statement opens a local cursor. Opening a cursor means that the associated query is executed and the that the result set is kept available for subsequent processing by the FETCH statement. The cursor must have been declared in the declarations section of the PSQL program.

Attempts to open a cursor that is already open, or attempts to open a named FOR SELECT cursor will fail and generate a run-time exception. All cursors which were not explicitly closed will be closed automatically on exit from the current PSQL program.

Examples

The following PSQL program opens a cursor, fetches a single row and then closes the cursor:

DECLARE RNAME CHAR(31); DECLARE C CURSOR FOR (SELECT RDB$RELATION_NAME FROM RDB$RELATIONS); BEGIN OPEN C; FETCH C INTO :RNAME; CLOSE C; END

See also

CLOSE statement, FETCH statement.

Page 128: Firebird 2.0 PSQL Reference Manual

POST_EVENT STATEMENT

Pupose

Use the POST_EVENT statement to signal a named event to the user application.

Syntax

<post_event_stmt> ::= POST_EVENT <psql_expr>;

Element Description

psql_expr A PSQL expression evaluating to a string value

Semantics

POST_EVENT posts an event to the event manager. When an event occurs, this statement will notify the event manager, which alerts applications waiting for the named event.

The event name can be a maximum of 78 characters in length.

Examples

The below example shows a valid use of the POST_EVENT statement:

POST_EVENT 'currency_table_updated'

See also

See the C/C++ Programming Manual for more information on handling events received by your application.

Page 129: Firebird 2.0 PSQL Reference Manual

SELECT INTO STATEMENT

Pupose

Use the SELECT INTO statement to retrieve a single row from a table. The PSQL select statement is identical to the SQL select statement followed by an INTO clause and a semicolon.

Syntax

<psql_select_stmt> ::= <select_stmt> INTO <var_list> ; <var_list> ::= <variable_name> | <variable_name> , <var_list> <variable_name> ::= <identifier>

Element Description

select_stmt A SQL insert statement as defined in the SQL Reference manual.

variable_name The name of a local variable of the enclosing body or of a parameter of the enclosing procedure definition.

Semantics

See the SQL Reference Manual for a description of the select statement.

The select statement must return exactly one row. If it returns zero or more than one row, a run-time error occurs.

Examples

The below is an example of a valid INSERT statement in PSQL:

SELECT COUNT(*) FROM rdb$relations INTO :table_c ount

See also

DELETE, UPDATE and INSERT

Page 130: Firebird 2.0 PSQL Reference Manual

SUSPEND STATEMENT

Pupose

Use SUSPEND to return a row of data from a procedure to its caller.

Syntax

<suspend_stmt> ::= SUSPEND ;

Semantics

Suspends execution of a PSQL routine until the next value is requested by the calling application, and returns output values, if any, to the calling application.

If the procedure is called from a select statement, processing will continue at the statement following SUSPEND when the next row of data is needed. Use the EXIT statement – or let the code path end at the final END of the body – to signal that there are no more rows to return.

If the procedure is called from a EXECUTE PROCEDURE statement, then SUSPEND has the same effect as EXIT. This usage is legal, but not recommended.

Examples

The below creates a procedure that returns the a series of integers and stops as soon as a value larger than 1000 has been reached.

CREATE PROCEDURE range RETURNING ( a INTEGER ) AS DECLARE i INTEGER = 1; DECLARE j INTEGER = 1; BEGIN a = i + j; i = j; j = a; IF (a>1000) THEN EXIT; SUSPEND; END;

See also

EXIT statement; PSQL Programs; See the SQL Reference Manual for a description of using procedures in SELECT statements.

Page 131: Firebird 2.0 PSQL Reference Manual

UPDATE STATEMENT

Pupose

Use the UPDATE statement to update new rows into a table. The PSQL update statement is identical to the SQL update statement followed by a semicolon.

Syntax

<psql_update_stmt> ::= <update_stmt> ;

Element Description

update_stmt A SQL update statement as defined in the SQL Reference manual.

Semantics

See the SQL Reference Manual for a description of the update statement.

Examples

The below is an example of a valid UPDATE statement in PSQL:

UPDATE table1 SET salary = :new_sal WHERE id = : emp_id;

See also

DELETE, INSERT and SELECT

Page 132: Firebird 2.0 PSQL Reference Manual

WHILE DO STATEMENT

Pupose

Use the WHILE DO statement to repeat a PSQL statement as long as a condition holds true.

Syntax

<while_stmt> ::= [ <label : ] WHILE ( <psql_condition> ) DO <psql_statement> <label> ::= <identifier>

Element Description

label A label naming the loop

psql_condition A PSQL condition. See the section on Conditions for more information.

psql_statement A PSQL statement. Often this will be a compound statement.

Semantics

The WHILE DO statement is a looping construct that repeats a statement – usually a compund statement – as long as a condition is true. The condition is tested at the start of each loop.

Examples

The below example shows a valid use of the WHEN DO statement:

WHILE (i<23) DO i=i+1;

See also

LEAVE statement

Page 133: Firebird 2.0 PSQL Reference Manual

Legal information

Unless otherwise indicated, this Web Site and its contents are the property of Janus Ventures BV ("Janus"). The copyright and all other intellectual property rights in the material contained on this Web Site belongs to Janus or its licensors. The trademarks appearing on this Web Site are protected by the laws of the Netherlands and international trademark laws.

In accessing this Web Site, you agree that the Web Site is made available for your personal, non-commercial use only. Unless you have Janus' prior written permission, you are not permitted to copy, broadcast, make available to the public, download, store (in any medium), transmit, show or play in public, adapt or change in any way the material (or any part of it) contained on this Web Site for any purpose whatsoever.

THIS WEB SITE AND ITS CONTENT IS PROVIDED FOR USE "AS IS". JANUS MAKES NO REPRESENTATIONS OR WARRANTIES WITH RESPECT TO THIS WEB SITE OR ITS CONTENTS, ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF SATISFACTORY QUALITY AND FITNESS FOR PURPOSE RELATING TO THIS WEB SITE AND/OR ITS CONTENT AND/OR ANY WEB SITE TO WHICH IS LINKED ARE HEREBY TO THE FULLEST EXTENT PERMITTED BY LAW EXCLUDED. NO REPRESENTATIONS OR WARRANTIES ARE GIVEN AS TO THE ACCURACY OR COMPLETENESS OF THE INFORMATION PROVIDED ON THIS WEB SITE, OR ANY WEB SITE TO WHICH IT IS LINKED.

In no event shall Janus or its employees, agents, suppliers, or contractors be liable for any damages of any nature, including without limitation any consequential loss, loss of income or profit, loss of or damage to property, claims of third parties, or any other loss, cost, claim or expense of any kind or character arising out of or in connection with the use of this Web Site, its content or any Web Site with which it is linked. This exclusion and limitation only applies to the extent permitted by law.