firebird 2.0 psql reference manual
TRANSCRIPT
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
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.
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:
* 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
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
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
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
FOR SELECT PROJ_ID FROM EMPLOYEE_PROJECT WHERE EMP_NO = :emp_no INTO :proj_id DO SUSPEND; END
See Also
CREATE PROCEDURE, DROP PROCEDURE
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.
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
• 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.
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
(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
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
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.
See Also
CREATE TRIGGER, ALTER TRIGGER
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
See Also
CREATE TRIGGER, DROP TRIGGER
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.
• 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.
• 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
• 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
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:
• 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.
• 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.
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
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.
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
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
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
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.
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:
• 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
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
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.
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
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>
<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
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
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
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
(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
(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
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>
| <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
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
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
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
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
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
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
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.
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
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
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
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
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.
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
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'
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,
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
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.
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
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
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
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
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
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).
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
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.
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
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.
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
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
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
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
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
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
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
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
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
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
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.
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.
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
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
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
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>
| <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
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
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
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
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'
name = 'John Smith'
See also
IF NULL, Group Comparison Conditions
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:
• 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
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
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
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
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
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.
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
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
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
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
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
| 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
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
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
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
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
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;
See also
DEFINING PROCEDURES
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
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.
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
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
OPEN statement, CLOSE statement, FOR SELECT statement.
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
EXECUTE INTO statement, SELECT INTO statement, BREAK statement. See the SQL Reference Manual for a full discussion of SQL statements.
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
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.
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
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
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
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.
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.
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.
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
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.
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
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
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.