About me 
Lucas Franzen 
Frred Software GmbH 
– Packing and shipping software 
– ERP add-on (SAP, Navision/Dynamics AX/ proAlpha, Baan, etc.) 
– All installations (~100) with Firebird (1.5) 
– Started with Interbase 4.0 in 1996 
– Firebird since the very beginning (Version 0.9) 
– Founding member oft the Firebird foundation 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 1
About this session 
● General Overview 
● How to write stored procedures 
● How to interact with stored procedures 
● Debugging / testing 
● Examples / example applications 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 2
What are STORED PROCEDURES? 
● Stored procedures are precompiled functions and queries, which are 
stored in the database. 
● They offer a lot of SQL-enhancements in complexity and can speed up 
data procession significantly. 
● In stored procedures there's the whole range of SQL-DML (Data 
Manipulation Language) available. 
● General restrictments: 
● No dynamic SQL statements available 
● No DDL (Data Definition Language) available. 
● Except using: EXECUTE STATEMENT 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 3
Why using Stored Procedures? 
● Executed on the server 
● Increased speed 
● Lower network traffic 
● PSQL offers more flexibility through SQL-enhancements 
● Batch processing within a single call / execution 
● Using as a Black-Box 
● Enhancement of permissions 
● Centralizing business-rules 
● Posting events 
● Executable from triggers 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 4
Restrictions 
● Domains (available since FB2) 
● No DDL statements (Create / alter / drop) unless using 
EXECUTE STATEMENT 
● No dynamic SQL-Statements 
● Example: 
It's not possible to pass in the name of a table as a parameter 
and use this parameter for dynamic SQL within the stored 
procedure. 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 5
Inside the database 
Stored procedures in the system tables 
RDB$PROCEDURES 
RDB$PROCEDURE_PARAMETERS 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 6
PSQL 
Procedural Structured Query Language 
• PSQL is Standard SQL plus some extensions, like 
– declare variable 
– if .. then .. else .. 
– while ... 
– suspend 
– when .. 
– do .. begin .. end 
– for select .. do .. begin .. end 
– leave 
– exit 
– ... 
• As it is used within triggers 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 7
PSQL 
In procedures the all SQL features can be used 
Not only 
SELECT, UPDATE, DELETE, ... are available 
But also 
LIKE, CONTAINING, STARTING WITH, ... 
This is not restricted to queries within the procedure 
it's also perfectly valid to use these commands for variable comparisons. 
IF ( VARIABLE LIKE '_N_' ) THEN .... 
IF ( VARIABLE STARTING 'Luc' ) THEN .... 
IF ( VARIABLE CONTAINING 'ire' ) THEN .... 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 8
Writing a Stored Procedure 
Example 1: 
SET TERM #; 
CREATE PROCEDURE SP_SUM_UP ( 
VAL_1 INTEGER, 
VAL_2 INTEGER 
) 
RETURNS ( NEW_SUM INTEGER ) 
AS BEGIN 
NEW_SUM = VAL_1 + VAL_2; 
END # 
SET TERM ;# 
Processing variables 
Processing table values 
(i.e. data) 
Example 2: 
SET TERM #; 
CREATE PROCEDURE SP_GET_COUNTRY_DATA (ID INTEGER ) 
RETURNS ( 
ISO CHAR(2), 
CNAME VARCHAR(40), 
CARPLATE VARCHAR(3) 
) 
AS BEGIN 
SELECT CT_ISO, CT_NAME, CT_CAR 
FROM COUNTRY 
WHERE CT_ID = :ID 
INTO :ISO, :CNAME, :CARPLATE; 
END # 
SET TERM ;# 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 9
The COLON : 
• When does a variable need the colon as a prefix? 
There's a lot of confusion about when to add the colon, when not. 
• In general: 
A colon has to be used when the variable is used in a SQL-statement. 
(Otherwise SQL would try to use it as a fieldname). 
USE THE COLON DON'T USE THE COLON 
SELECT .. FROM .. 
INTO :VAR1, :VAR2 
INSERT INTO .. 
VALUES (:VAR1, :VAR2) 
UPDATE ... SET 
FIELD1 = :VAR1 ... 
... WHERE FIELD1 = :VAR1 
IF ( VAR1 = SOMEVALUE ) THEN ... 
(Comparing values) 
VAR1 = VAR2 
(Assigning values outside DML) 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 10
SET TERM 
SQL statements are terminated by a semicolon (;). 
In SPs there can be multiple SQL statements, each of these has to be terminated by the semicolon. 
But since the procedure itself is a SQL (DDL) statement to the database engine it has to be 
terminated as well. 
To get this working there's the SET TERM [new terminator] command. 
SET TERM assigns a new terminating symbol to SQL, replacing the semicolon. 
After executing the SQL it has to be reset to the original value. 
Example: 
SET TERM #;  the new terminating symbol is now # 
CREATE PROCEDURE ... 
.... code here, including ; .... 
END #  # = end of procedure code 
SET TERM ;#  resetting terminating symbol to the original ; 
Note: 
Some tools might automatically do this job for you !!! 
When receiving the error message (-104: Unexpected end of command) the termination is missing. 
When receiving the error message (-104: Token unknown - line n, char 5. TERM) the terminators 
where already added by the tool. 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 11
Executable or selectable? 
• Stored procedures can be invoked in two separate ways. 
– EXECUTE PROCEDURE (<INPUT_PARAMS>) 
An executable procedure returns ONE set of its output params. 
– SELECT 
<FIELD_LIST> 
FROM PROCEDURE 
<WHERE> 
<ORDER BY> 
A selectable procedure returns 0..n sets of its output parameters as FIELDS. 
Such a procedure has to be queried like a TABLE. 
The resultset of a selectable procedure can be limited / sorted by WHERE / 
ORDER BY / GROUP BY clauses, though this slows down execution. 
But there are situations and complex queries where this can be very help- and 
powerful (i.e. ordering a resultset by a value that's calculated and returned by the 
SP itself). 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 12
Executable or selectable? 
• Executable Procedure 
Example 3: 
CREATE PROCEDURE SP_SUM_UP ( 
VAL_1 INTEGER, 
VAL_2 INTEGER, 
) 
RETURNS ( NEW_SUM INTEGER ) 
AS BEGIN 
NEW_SUM = VAL_1 + VAL_2; 
END 
• Selectable Procedure 
Example 4: 
CREATE PROCEDURE SEL_CUSTOMER_IN_CITY ( CITY_NAME VARCHAR(40) ) 
RETURNS ( 
CUST_NAME VARCHAR(40), 
CUST_NO VARCHAR(10) 
) 
AS BEGIN 
FOR SELECT CUST_NAME, CUST_NO 
FROM CUSTOMERS 
WHERE CUST_CITY = :CITY_NAME 
INTO :CUST_NAME, :CUST_NO 
DO BEGIN 
SUSPEND; 
END 
END 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 13
Writing and compiling pitfalls 
● Do ALWAYS initialize your variables! 
Note: 
Since FB1.5 the variable can be initialized within the declaration! 
DECLARE VARIABLE ABC VARCHAR(3) = 'ABC'; 
When a variable is used within a loop (FOR SELECT ... DO , WHILE ( ) DO ...) 
always re-initialize variables within this loop! 
● Why is that? 
If there's a select within a loop which doesn't return anything 
(keep in mind: nothing <> NULL) then the current variable values aren't touched at 
all... 
So this might lead to interesting (but unwanted) results... 
--> Example application 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 14
Writing and compiling pitfalls 
● Most common errors caused in / from procedures: 
– Arithmetic exception string truncation or overflow 
fill all the table fields to their maximum! 
( Example, next page) 
– Multiple rows in singleton select 
Will occur whenever a SELECT FROM .. INTO –will return more than one 
record and is not within a FOR..SELECT loop. 
Be sure to have selects like this using an UNIQUE INDEX (caution: NULL 
can be used within an unique index since FB1.5) or other means of 
limitation (MIN, FIRST 1) 
--> Example application 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 15
The Black Box 
● Use procedures as a black box, 
for example 
– Between different databases 
– Within a database, when different teams are working at different tasks 
– Complex tasks can be executed within the database and the result is 
published by a stored procedure 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 16
The Black Box 
● Example 
Frred Package System 
Scan delivery note 
Search in Frred 
Database 
ERP System Database 
Request 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 17
Permission and access control 
● Use procedures to give access to just some tables / fields 
SET TERM #; 
CREATE PROCEDURE SEL_CUSTOMERS returns ( 
CUSTOMER_ID BigInt, 
CUSTOMER_NAME VarChar(40) 
) 
AS 
BEGIN 
FOR SELECT 
CUST_ID, CUST_NAME 
FROM CUSTOMERS 
INTO :CUSTOMER_ID, :CUSTOMER_NAME 
DO BEGIN 
SUSPEND; 
END 
END # 
SET TERM ;# 
/* grant the execution of the procedure to PUBLIC */ 
GRANT EXECUTE ON PROCEDURE SEL_CUSTOMERS TO PUBLIC; 
/* grant SELECT on the table CUSTOMERS to the procedure */ 
GRANT SELECT ON CUSTOMERS TO PROCEDURE SEL_CUSTOMERS; 
--> Example application 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 18
Calling procedures within 
procedures 
● Every procedure can invoke another procedure. 
Which way this is happening depends if it's an 
executable 
or 
selectable procedure 
● Calling an executable procedure 
– EXECUTE PROCEDURE <PROCNAME> [Params] 
RETURNING VALUES [OUTPUT PARAMS] 
● Calling a selectabe procedure 
– SELECT [Fieldlist] FROM <PROCNAME> 
INTO :Field1...:Fieldn 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 19
Recursive procedures 
● Since procedures can call procedures a procedure can call itself, too 
● With this recursion you can build trees 
● Watch for maximum depth! 
--> Example application 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 20
Example: Freight calculation 
Freight 
calculations Services 
Countries Linktable Shippers 
--> Example application 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 21
Example: Freight calculation 
● STEP 1 
– Select all matching services for 
● The destination country 
● The shipper 
● Service type 
SSEELLEECCTT ** FFRROOMM SSPP__GGEETT__SSEERRVVIICCEESS__AANNDD__SSHHIIPPPPEERRSS 
● STEP 2 
– If the shipper is not initialized / given: 
● Get a list of all shippers which are linked to the destination country 
– Now get a list of every active service for the shipper 
SSEELLEECCTT ** FFRROOMM SSPP__GGEETT__AACCTTIIVVEE__SSEERRVVIICCEESS 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 22
Example: Freight calculation 
● STEP 3 
– Store all these informations in objects on the client side. 
● STEP 4 
– Now iterate / loop through all these objects and call the calculation 
procedure for every service 
SSEELLEECCTT ** FFRROOMM SSPP__CCAALLCCUULLAATTEE__SSEERRVVIICCEE 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 23
Example: Freight calculation 
● INSIDE THE PROCEDURE 
– Select the basic settings for this service 
– Check the general settings 
– Depending on the settings in the service just call the appropriate 
procedure to calculate the freight 
● Calculation is based on zip-codes 
– Procedure SEL_ZIPCODE_IDENT 
– Procedure SEL_ZIPCODE_LEFT 
– Procedure SEL_ZIPCODE_NORMALIZED 
● Based on distances or city names 
– Select directly from CALCULATION TABLE 
● Based on cities 
● Not based on zones at all? 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 24
Example: Freight calculation 
● INSIDE THE PROCEDURE (continued) 
– Is the service still valid so far? 
– No? Exit and return error 
– Yes? CALCULATE! 
Call the procedure SSEELLEECCTT ** FFRROOMM SSEELL__FFRREEIIGGHHTTCCHHAARRGGEESS 
● Within this procedure the kind of calculation will be examined and according 
to that the reuslt will be calculated by 
– SP_CALC_DIRETLY 
– SP_CALC_BY_WEIGHT 
– SP_CALC_BY_DISTANCE 
... 
– Calculate extra costs (Diesel surcharge) 
--> Example application 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 25
Execute statement 
● Remember: 
No DDL-statements / dynamic SQL within procedures 
● Use EXECUTE STATEMENT to bypass these restrictions 
● EXECUTE STATEMENT is potentially unsafe: 
– No possibilty to check the syntax. 
– No check of dependencies! 
– Operations are slow, since embedded statements have to be prepared 
before every execution. 
– Datatypes of the return-values are strictly checked to avoid typecasting-errors. 
For example the string „1234“ could usually be converted to the 
Integer 1234; The string „abc“ would cause an converting error. 
– When the procedure has certain privileges on some objects, these will 
not be inherited to the execute statement! 
The privileges are restricted to the ones the user that's executing the 
procedure has got in general! 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 26
Execute statement 
● Since FB1.5 there's Execute Statement, which offers the possibility 
to use dynamic SQL and even DDL-Statements within procedures. 
The syntax: 
– Executes <string> as SQL-Operation, not returnign anything--> 
INSERT, UPDATE, DELETE, EXECUTE PROCEDURE or any DDL operation, 
BUT CREATE/DROP DATABASE. 
EXECUTE STATEMENT <string>; 
– Executes <string> as SQL-Operation, returning a single record. 
Of course only singleton SELECT Operatoren qualify for this use of 
EXECUTE STATEMENT. 
EXECUTE STATEMENT <string> INTO :var1, […, :varn] ; 
– Executes <string> as SQL-Operation, returning a any number of records. Every 
SELECT Operator can be used with this kind of EXECUTE STATEMENT 
FOR EXECUTE STATEMENT <string> 
INTO :var1, …, :varn DO 
<compound-statement>; 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 27
Reporting 
● Stored procedures can be very useful for reporting 
● Remember: 
Selectable procedure can be accessed like any table 
● For rather „unstructured“ formulas where master/detail areas are not 
perfectly separated you can process the data in a stored procedure 
and return it in a form the report can handle 
● Ordering / Grouping that's basing on complex calculations and data 
manipulation sometimes cannot be done with SQL. 
The stored procedure can return these calculated fields and you can 
order /group on that resultset 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 28
Data transfer 
● Stored procedures are perfect for database-internal datatransfer. 
– Transferring data from one/more table(s) to (an)other table(s) 
– Copying records 
● If using this keep in mind: 
– If a table the procedure is based on is being altered the procedure might 
be altered as well 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 29
Testing stored procedures 
● Before taking a procedure into production test it thoroughly as well as 
every program part that's using it. 
● Most common errors by SPs: 
– Arithmetic exception string truncation or overflow 
Fill all the table fields to their maximum! 
– Multiple rows in singleton select 
Will occur whenever a SELECT FROM .. INTO –will return more than one 
record and is not within a FOR..SELECT loop. 
Be sure to have selects like this using an UNIQUE INDEX (caution: NULL 
can be used within an unique index since FB1.5) or other means of 
limitation (MIN, FIRST 1) 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 30
Debugging Stored Procedures 
● Use Tools 
– IB Expert 
– Database Workbench 
– ... 
● On your own: 
Catch an exception 
by using WHEN ANY 
– Use 
INSERT STATEMENTS 
to store information from 
with the procedure in a 
table 
– Use variables to identify 
wherethe problem occured 
BEISPIEL: 
SET TERM #; 
CREATE PROCEDURE SEL_PROCEDURE 
RETURNS ( 
FIELD_1 VARCHAR(40), 
... 
ERROR_AT INTEGER 
) 
AS BEGIN 
ERROR_AT = 0; 
/* Step 1 */ 
ERROR_AT = 1; 
... CODE ... 
/* Step 2 */ 
ERROR_AT = 2; 
... CODE ... 
/* End of Code */ 
WHEN ANY DO 
BEGIN 
/* Return Variable ERROR_AT */ 
SUSPEND; 
END 
END # 
SET TERM ;# 
On exception the WHEN ANY will be executed: 
 by looking at ERROR_AT variable you'll find out 
where it occured. 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 31
Transactions 
● Stored Procedures always run in the context of the invoking 
application! 
● Stored Procedures can't use COMMIT or ROLLBACK within their 
body. 
● So what's happening when there's an error with a procedure 
Do a Rollback or a Commit? 
– WITHOUT EXCEPTION HANDLING 
All changes will be lost 
– WITH EXCEPTION HANDLING 
All changes can be committed 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 32
Changing existing procedures 
● CAUTION 
when changing procedures that are used by other procedures! 
If such a SP is changed always keep the follwoing in mind: 
– When changing the input parameters: 
Do change all other procedures which use it in advance. This can be 
done by dropping, altering to an empty body or just removing the calling 
reference. 
– When changing the output parameters: 
do the same, when: 
● the changed procedure is invoked as an executable procedure and 
the return parameters are defined by RETURNING_VALUES 
● The changed procedure is invoked as a selectable procedure and 
SELECT * FROM ... INTO... is used. 
● Thus you can be sure that the database is not in a (temporary?) state 
where Metadata are not cosistent. 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 33
HELP! 
● If a stored procedure cannot be altered or deleted any longer, 
and even backup / restore / gfix is of no avail: 
– Kill the procedure-Source in the database! 
SYSTEM TABLE: RDB$PROCEDURES: 
CREATE TABLE RDB$PROCEDURES ( 
RDB$PROCEDURE_NAME CHAR (31), 
RDB$PROCEDURE_ID SMALLINT, 
RDB$PROCEDURE_INPUTS SMALLINT, 
RDB$PROCEDURE_OUTPUTS SMALLINT, 
RDB$DESCRIPTION BLOB, 
RDB$PROCEDURE_SOURCE BLOB, 
RDB$PROCEDURE_BLR BLOB, 
RDB$SECURITY_CLASS CHAR (31), 
RDB$OWNER_NAME CHAR (31), 
RDB$RUNTIME BLOB, 
RDB$SYSTEM_FLAG SMALLINT 
); 
UPDATE RDB$PROCEDURES SET 
RDB$PROCEDURE_BLR = NULL 
WHERE RDB$PROCEDURE_NAME = <PROCEDURE_NAME> 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 34
The END 
AANNYY QQUUEESSTTIIOONNSS?? 
Feel free to contact me: 
lucas.franzen@frred.de 
luc@frred.de 
Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 35

Stored procedures in Firebird

  • 1.
    About me LucasFranzen Frred Software GmbH – Packing and shipping software – ERP add-on (SAP, Navision/Dynamics AX/ proAlpha, Baan, etc.) – All installations (~100) with Firebird (1.5) – Started with Interbase 4.0 in 1996 – Firebird since the very beginning (Version 0.9) – Founding member oft the Firebird foundation Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 1
  • 2.
    About this session ● General Overview ● How to write stored procedures ● How to interact with stored procedures ● Debugging / testing ● Examples / example applications Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 2
  • 3.
    What are STOREDPROCEDURES? ● Stored procedures are precompiled functions and queries, which are stored in the database. ● They offer a lot of SQL-enhancements in complexity and can speed up data procession significantly. ● In stored procedures there's the whole range of SQL-DML (Data Manipulation Language) available. ● General restrictments: ● No dynamic SQL statements available ● No DDL (Data Definition Language) available. ● Except using: EXECUTE STATEMENT Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 3
  • 4.
    Why using StoredProcedures? ● Executed on the server ● Increased speed ● Lower network traffic ● PSQL offers more flexibility through SQL-enhancements ● Batch processing within a single call / execution ● Using as a Black-Box ● Enhancement of permissions ● Centralizing business-rules ● Posting events ● Executable from triggers Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 4
  • 5.
    Restrictions ● Domains(available since FB2) ● No DDL statements (Create / alter / drop) unless using EXECUTE STATEMENT ● No dynamic SQL-Statements ● Example: It's not possible to pass in the name of a table as a parameter and use this parameter for dynamic SQL within the stored procedure. Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 5
  • 6.
    Inside the database Stored procedures in the system tables RDB$PROCEDURES RDB$PROCEDURE_PARAMETERS Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 6
  • 7.
    PSQL Procedural StructuredQuery Language • PSQL is Standard SQL plus some extensions, like – declare variable – if .. then .. else .. – while ... – suspend – when .. – do .. begin .. end – for select .. do .. begin .. end – leave – exit – ... • As it is used within triggers Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 7
  • 8.
    PSQL In proceduresthe all SQL features can be used Not only SELECT, UPDATE, DELETE, ... are available But also LIKE, CONTAINING, STARTING WITH, ... This is not restricted to queries within the procedure it's also perfectly valid to use these commands for variable comparisons. IF ( VARIABLE LIKE '_N_' ) THEN .... IF ( VARIABLE STARTING 'Luc' ) THEN .... IF ( VARIABLE CONTAINING 'ire' ) THEN .... Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 8
  • 9.
    Writing a StoredProcedure Example 1: SET TERM #; CREATE PROCEDURE SP_SUM_UP ( VAL_1 INTEGER, VAL_2 INTEGER ) RETURNS ( NEW_SUM INTEGER ) AS BEGIN NEW_SUM = VAL_1 + VAL_2; END # SET TERM ;# Processing variables Processing table values (i.e. data) Example 2: SET TERM #; CREATE PROCEDURE SP_GET_COUNTRY_DATA (ID INTEGER ) RETURNS ( ISO CHAR(2), CNAME VARCHAR(40), CARPLATE VARCHAR(3) ) AS BEGIN SELECT CT_ISO, CT_NAME, CT_CAR FROM COUNTRY WHERE CT_ID = :ID INTO :ISO, :CNAME, :CARPLATE; END # SET TERM ;# Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 9
  • 10.
    The COLON : • When does a variable need the colon as a prefix? There's a lot of confusion about when to add the colon, when not. • In general: A colon has to be used when the variable is used in a SQL-statement. (Otherwise SQL would try to use it as a fieldname). USE THE COLON DON'T USE THE COLON SELECT .. FROM .. INTO :VAR1, :VAR2 INSERT INTO .. VALUES (:VAR1, :VAR2) UPDATE ... SET FIELD1 = :VAR1 ... ... WHERE FIELD1 = :VAR1 IF ( VAR1 = SOMEVALUE ) THEN ... (Comparing values) VAR1 = VAR2 (Assigning values outside DML) Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 10
  • 11.
    SET TERM SQLstatements are terminated by a semicolon (;). In SPs there can be multiple SQL statements, each of these has to be terminated by the semicolon. But since the procedure itself is a SQL (DDL) statement to the database engine it has to be terminated as well. To get this working there's the SET TERM [new terminator] command. SET TERM assigns a new terminating symbol to SQL, replacing the semicolon. After executing the SQL it has to be reset to the original value. Example: SET TERM #;  the new terminating symbol is now # CREATE PROCEDURE ... .... code here, including ; .... END #  # = end of procedure code SET TERM ;#  resetting terminating symbol to the original ; Note: Some tools might automatically do this job for you !!! When receiving the error message (-104: Unexpected end of command) the termination is missing. When receiving the error message (-104: Token unknown - line n, char 5. TERM) the terminators where already added by the tool. Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 11
  • 12.
    Executable or selectable? • Stored procedures can be invoked in two separate ways. – EXECUTE PROCEDURE (<INPUT_PARAMS>) An executable procedure returns ONE set of its output params. – SELECT <FIELD_LIST> FROM PROCEDURE <WHERE> <ORDER BY> A selectable procedure returns 0..n sets of its output parameters as FIELDS. Such a procedure has to be queried like a TABLE. The resultset of a selectable procedure can be limited / sorted by WHERE / ORDER BY / GROUP BY clauses, though this slows down execution. But there are situations and complex queries where this can be very help- and powerful (i.e. ordering a resultset by a value that's calculated and returned by the SP itself). Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 12
  • 13.
    Executable or selectable? • Executable Procedure Example 3: CREATE PROCEDURE SP_SUM_UP ( VAL_1 INTEGER, VAL_2 INTEGER, ) RETURNS ( NEW_SUM INTEGER ) AS BEGIN NEW_SUM = VAL_1 + VAL_2; END • Selectable Procedure Example 4: CREATE PROCEDURE SEL_CUSTOMER_IN_CITY ( CITY_NAME VARCHAR(40) ) RETURNS ( CUST_NAME VARCHAR(40), CUST_NO VARCHAR(10) ) AS BEGIN FOR SELECT CUST_NAME, CUST_NO FROM CUSTOMERS WHERE CUST_CITY = :CITY_NAME INTO :CUST_NAME, :CUST_NO DO BEGIN SUSPEND; END END Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 13
  • 14.
    Writing and compilingpitfalls ● Do ALWAYS initialize your variables! Note: Since FB1.5 the variable can be initialized within the declaration! DECLARE VARIABLE ABC VARCHAR(3) = 'ABC'; When a variable is used within a loop (FOR SELECT ... DO , WHILE ( ) DO ...) always re-initialize variables within this loop! ● Why is that? If there's a select within a loop which doesn't return anything (keep in mind: nothing <> NULL) then the current variable values aren't touched at all... So this might lead to interesting (but unwanted) results... --> Example application Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 14
  • 15.
    Writing and compilingpitfalls ● Most common errors caused in / from procedures: – Arithmetic exception string truncation or overflow fill all the table fields to their maximum! ( Example, next page) – Multiple rows in singleton select Will occur whenever a SELECT FROM .. INTO –will return more than one record and is not within a FOR..SELECT loop. Be sure to have selects like this using an UNIQUE INDEX (caution: NULL can be used within an unique index since FB1.5) or other means of limitation (MIN, FIRST 1) --> Example application Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 15
  • 16.
    The Black Box ● Use procedures as a black box, for example – Between different databases – Within a database, when different teams are working at different tasks – Complex tasks can be executed within the database and the result is published by a stored procedure Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 16
  • 17.
    The Black Box ● Example Frred Package System Scan delivery note Search in Frred Database ERP System Database Request Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 17
  • 18.
    Permission and accesscontrol ● Use procedures to give access to just some tables / fields SET TERM #; CREATE PROCEDURE SEL_CUSTOMERS returns ( CUSTOMER_ID BigInt, CUSTOMER_NAME VarChar(40) ) AS BEGIN FOR SELECT CUST_ID, CUST_NAME FROM CUSTOMERS INTO :CUSTOMER_ID, :CUSTOMER_NAME DO BEGIN SUSPEND; END END # SET TERM ;# /* grant the execution of the procedure to PUBLIC */ GRANT EXECUTE ON PROCEDURE SEL_CUSTOMERS TO PUBLIC; /* grant SELECT on the table CUSTOMERS to the procedure */ GRANT SELECT ON CUSTOMERS TO PROCEDURE SEL_CUSTOMERS; --> Example application Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 18
  • 19.
    Calling procedures within procedures ● Every procedure can invoke another procedure. Which way this is happening depends if it's an executable or selectable procedure ● Calling an executable procedure – EXECUTE PROCEDURE <PROCNAME> [Params] RETURNING VALUES [OUTPUT PARAMS] ● Calling a selectabe procedure – SELECT [Fieldlist] FROM <PROCNAME> INTO :Field1...:Fieldn Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 19
  • 20.
    Recursive procedures ●Since procedures can call procedures a procedure can call itself, too ● With this recursion you can build trees ● Watch for maximum depth! --> Example application Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 20
  • 21.
    Example: Freight calculation Freight calculations Services Countries Linktable Shippers --> Example application Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 21
  • 22.
    Example: Freight calculation ● STEP 1 – Select all matching services for ● The destination country ● The shipper ● Service type SSEELLEECCTT ** FFRROOMM SSPP__GGEETT__SSEERRVVIICCEESS__AANNDD__SSHHIIPPPPEERRSS ● STEP 2 – If the shipper is not initialized / given: ● Get a list of all shippers which are linked to the destination country – Now get a list of every active service for the shipper SSEELLEECCTT ** FFRROOMM SSPP__GGEETT__AACCTTIIVVEE__SSEERRVVIICCEESS Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 22
  • 23.
    Example: Freight calculation ● STEP 3 – Store all these informations in objects on the client side. ● STEP 4 – Now iterate / loop through all these objects and call the calculation procedure for every service SSEELLEECCTT ** FFRROOMM SSPP__CCAALLCCUULLAATTEE__SSEERRVVIICCEE Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 23
  • 24.
    Example: Freight calculation ● INSIDE THE PROCEDURE – Select the basic settings for this service – Check the general settings – Depending on the settings in the service just call the appropriate procedure to calculate the freight ● Calculation is based on zip-codes – Procedure SEL_ZIPCODE_IDENT – Procedure SEL_ZIPCODE_LEFT – Procedure SEL_ZIPCODE_NORMALIZED ● Based on distances or city names – Select directly from CALCULATION TABLE ● Based on cities ● Not based on zones at all? Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 24
  • 25.
    Example: Freight calculation ● INSIDE THE PROCEDURE (continued) – Is the service still valid so far? – No? Exit and return error – Yes? CALCULATE! Call the procedure SSEELLEECCTT ** FFRROOMM SSEELL__FFRREEIIGGHHTTCCHHAARRGGEESS ● Within this procedure the kind of calculation will be examined and according to that the reuslt will be calculated by – SP_CALC_DIRETLY – SP_CALC_BY_WEIGHT – SP_CALC_BY_DISTANCE ... – Calculate extra costs (Diesel surcharge) --> Example application Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 25
  • 26.
    Execute statement ●Remember: No DDL-statements / dynamic SQL within procedures ● Use EXECUTE STATEMENT to bypass these restrictions ● EXECUTE STATEMENT is potentially unsafe: – No possibilty to check the syntax. – No check of dependencies! – Operations are slow, since embedded statements have to be prepared before every execution. – Datatypes of the return-values are strictly checked to avoid typecasting-errors. For example the string „1234“ could usually be converted to the Integer 1234; The string „abc“ would cause an converting error. – When the procedure has certain privileges on some objects, these will not be inherited to the execute statement! The privileges are restricted to the ones the user that's executing the procedure has got in general! Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 26
  • 27.
    Execute statement ●Since FB1.5 there's Execute Statement, which offers the possibility to use dynamic SQL and even DDL-Statements within procedures. The syntax: – Executes <string> as SQL-Operation, not returnign anything--> INSERT, UPDATE, DELETE, EXECUTE PROCEDURE or any DDL operation, BUT CREATE/DROP DATABASE. EXECUTE STATEMENT <string>; – Executes <string> as SQL-Operation, returning a single record. Of course only singleton SELECT Operatoren qualify for this use of EXECUTE STATEMENT. EXECUTE STATEMENT <string> INTO :var1, […, :varn] ; – Executes <string> as SQL-Operation, returning a any number of records. Every SELECT Operator can be used with this kind of EXECUTE STATEMENT FOR EXECUTE STATEMENT <string> INTO :var1, …, :varn DO <compound-statement>; Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 27
  • 28.
    Reporting ● Storedprocedures can be very useful for reporting ● Remember: Selectable procedure can be accessed like any table ● For rather „unstructured“ formulas where master/detail areas are not perfectly separated you can process the data in a stored procedure and return it in a form the report can handle ● Ordering / Grouping that's basing on complex calculations and data manipulation sometimes cannot be done with SQL. The stored procedure can return these calculated fields and you can order /group on that resultset Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 28
  • 29.
    Data transfer ●Stored procedures are perfect for database-internal datatransfer. – Transferring data from one/more table(s) to (an)other table(s) – Copying records ● If using this keep in mind: – If a table the procedure is based on is being altered the procedure might be altered as well Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 29
  • 30.
    Testing stored procedures ● Before taking a procedure into production test it thoroughly as well as every program part that's using it. ● Most common errors by SPs: – Arithmetic exception string truncation or overflow Fill all the table fields to their maximum! – Multiple rows in singleton select Will occur whenever a SELECT FROM .. INTO –will return more than one record and is not within a FOR..SELECT loop. Be sure to have selects like this using an UNIQUE INDEX (caution: NULL can be used within an unique index since FB1.5) or other means of limitation (MIN, FIRST 1) Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 30
  • 31.
    Debugging Stored Procedures ● Use Tools – IB Expert – Database Workbench – ... ● On your own: Catch an exception by using WHEN ANY – Use INSERT STATEMENTS to store information from with the procedure in a table – Use variables to identify wherethe problem occured BEISPIEL: SET TERM #; CREATE PROCEDURE SEL_PROCEDURE RETURNS ( FIELD_1 VARCHAR(40), ... ERROR_AT INTEGER ) AS BEGIN ERROR_AT = 0; /* Step 1 */ ERROR_AT = 1; ... CODE ... /* Step 2 */ ERROR_AT = 2; ... CODE ... /* End of Code */ WHEN ANY DO BEGIN /* Return Variable ERROR_AT */ SUSPEND; END END # SET TERM ;# On exception the WHEN ANY will be executed:  by looking at ERROR_AT variable you'll find out where it occured. Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 31
  • 32.
    Transactions ● StoredProcedures always run in the context of the invoking application! ● Stored Procedures can't use COMMIT or ROLLBACK within their body. ● So what's happening when there's an error with a procedure Do a Rollback or a Commit? – WITHOUT EXCEPTION HANDLING All changes will be lost – WITH EXCEPTION HANDLING All changes can be committed Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 32
  • 33.
    Changing existing procedures ● CAUTION when changing procedures that are used by other procedures! If such a SP is changed always keep the follwoing in mind: – When changing the input parameters: Do change all other procedures which use it in advance. This can be done by dropping, altering to an empty body or just removing the calling reference. – When changing the output parameters: do the same, when: ● the changed procedure is invoked as an executable procedure and the return parameters are defined by RETURNING_VALUES ● The changed procedure is invoked as a selectable procedure and SELECT * FROM ... INTO... is used. ● Thus you can be sure that the database is not in a (temporary?) state where Metadata are not cosistent. Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 33
  • 34.
    HELP! ● Ifa stored procedure cannot be altered or deleted any longer, and even backup / restore / gfix is of no avail: – Kill the procedure-Source in the database! SYSTEM TABLE: RDB$PROCEDURES: CREATE TABLE RDB$PROCEDURES ( RDB$PROCEDURE_NAME CHAR (31), RDB$PROCEDURE_ID SMALLINT, RDB$PROCEDURE_INPUTS SMALLINT, RDB$PROCEDURE_OUTPUTS SMALLINT, RDB$DESCRIPTION BLOB, RDB$PROCEDURE_SOURCE BLOB, RDB$PROCEDURE_BLR BLOB, RDB$SECURITY_CLASS CHAR (31), RDB$OWNER_NAME CHAR (31), RDB$RUNTIME BLOB, RDB$SYSTEM_FLAG SMALLINT ); UPDATE RDB$PROCEDURES SET RDB$PROCEDURE_BLR = NULL WHERE RDB$PROCEDURE_NAME = <PROCEDURE_NAME> Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 34
  • 35.
    The END AANNYYQQUUEESSTTIIOONNSS?? Feel free to contact me: lucas.franzen@frred.de luc@frred.de Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen 35