1Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
About meLucas 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
2Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
About this session● General Overview● How to write stored procedures● How to interact with stored procedures● Debugging / testing● Examples / example applications
3Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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
4Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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
5Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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.
6Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
Inside the databaseStored procedures in the system tablesRDB$PROCEDURES
RDB$PROCEDURE_PARAMETERS
7Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
PSQLProcedural 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
8Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
PSQLIn procedures the all SQL features can be used
Not only SELECT, UPDATE, DELETE, ... are available
But alsoLIKE, 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 ....
9Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
Writing a Stored ProcedureExample 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 ;#
10Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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).
... WHERE FIELD1 = :VAR1
UPDATE ... SETFIELD1 = :VAR1 ...
VAR1 = VAR2(Assigning values outside DML)
INSERT INTO .. VALUES (:VAR1, :VAR2)
IF ( VAR1 = SOMEVALUE ) THEN ...(Comparing values)
SELECT .. FROM .. INTO :VAR1, :VAR2
DON'T USE THE COLONUSE THE COLON
11Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
SET TERMSQL 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 codeSET 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.
12Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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).
13Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
Executable or selectable?• Executable Procedure
• Selectable 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
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; ENDEND
14Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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
15Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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 selectWill 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
16Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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
17Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
The Black Box● Example
Frred Package System
Scan delivery note
Search in FrredDatabase
ERP System Database
Request
18Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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))ASBEGIN FOR SELECT CUST_ID, CUST_NAME FROM CUSTOMERS INTO :CUSTOMER_ID, :CUSTOMER_NAME DO BEGIN SUSPEND;ENDEND #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
19Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
Calling procedures within procedures
● Every procedure can invoke another procedure.Which way this is happening depends if it's an
executableorselectable procedure
● Calling an executable procedure– EXECUTE PROCEDURE <PROCNAME> [Params]
RETURNING VALUES [OUTPUT PARAMS]● Calling a selectabe procedure
– SELECT [Fieldlist] FROM <PROCNAME> INTO :Field1...:Fieldn
20Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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
21Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
Example: Freight calculation
--> Example application
Freightcalculations Services
Countries ShippersLinktable
22Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
Example: Freight calculation● STEP 1
– Select all matching services for● The destination country● The shipper● Service type
SELECT * FROM SP_GET_SERVICES_AND_SHIPPERSSELECT * FROM SP_GET_SERVICES_AND_SHIPPERS
● 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
SELECT * FROM SP_GET_ACTIVE_SERVICESSELECT * FROM SP_GET_ACTIVE_SERVICES
23Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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
SELECT * FROM SP_CALCULATE_SERVICESELECT * FROM SP_CALCULATE_SERVICE
24Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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?
25Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
Example: Freight calculation● INSIDE THE PROCEDURE (continued)
– Is the service still valid so far?
– No? Exit and return error– Yes? CALCULATE!
Call the procedure SELECT * FROM SEL_FREIGHTCHARGESSELECT * FROM SEL_FREIGHTCHARGES● 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
26Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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!
27Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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>;
28Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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
29Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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
30Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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 selectWill 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)
31Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
Debugging Stored Procedures● Use Tools
– IB Expert– Database Workbench– ...
● On your own:Catch an exceptionby using WHEN ANY – Use
INSERT STATEMENTS to store information fromwith the procedure in atable
– 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; ENDEND #SET TERM ;#
On exception the WHEN ANY will be executed: by looking at ERROR_AT variable you'll find out where it occured.
32Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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 procedureDo a Rollback or a Commit?
– WITHOUT EXCEPTION HANDLINGAll changes will be lost
– WITH EXCEPTION HANDLINGAll changes can be committed
33Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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.
34Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
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!
UPDATE RDB$PROCEDURES SET RDB$PROCEDURE_BLR = NULLWHERE RDB$PROCEDURE_NAME = <PROCEDURE_NAME>
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);
35Firebird Conference 2012 • Luxembourg • STORED PROCEDURES • Lucas Franzen
The END
ANY QUESTIONS?ANY QUESTIONS?
Feel free to contact me:
[email protected]@frred.de
Top Related