Matakuliah Tahun : T0413 : 2009 Stored Procedure, UDF and Triggers Pertemuan 9 Stored Procedures Server Client Application SQL #1 SQL #2 SQL #3 Network myproc SQL #1 CALL myproc SQL #2 SQL #3 Bina Nusantara University 3 Stored Procedures • Database objects that usually contain one or more SQL statements as well as procedural (business) logic • Executed and managed by DB2 (server-side objects) • Can be written using SQL PL, C/C++, Java, Cobol, CLR supported languages, and OLE • Benefits for using stored procedures include: – Centralized business logic that promotes code re-use – Improved security – Improved performance • In this workshop, we focus on SQL PL procedures because of their popularity, good performance and simplicity Bina Nusantara University 4 IBM Data Studio • Replaces the DB2 Developer Workbench of DB2 9 • Installed separately from DB2 9.5 • Based on Eclipse Creating your first SQL PL Stored Procedure Using the Command Editor: connect to sample create procedure p1 begin end Using the IBM Data Studio Bina Nusantara University 5 Basic stored procedure structure CREATE PROCEDURE proc_name [( {optional parameters} )] [optional procedure attributes] <statement> <statement> is a single statement, or a set of statements grouped by BEGIN [ATOMIC] ... END Optional stored procedure attributes LANGUAGE SQL RESULT SETS <n> (required if returning result sets) SPECIFIC my_unique_name ƒ can be same as procedure name ƒ highly recommended for manageability: –GRANT EXECUTE ON SPECIFIC PROCEDURE ... Bina Nusantara University –DROP SPECIFIC PROCEDURE ... 6 Parameters CREATE PROCEDURE proc(IN p1 INT, OUT p2 INT, INOUT p3 INT) ... IN - Input parameter OUT - Output parameter INOUT - Input and Output parameter All params must be provided in CALL statement Comments in SQL PL Stored Procedures -- This is an SQL-style comment /* This is a C-style coment */ (valid within SQL procedures ) Bina Nusantara University 7 Compound statements Compound Statement BEGIN [ATOMIC] <declare variables> <declare conditions> <declare statements> <declare cursors> <declare handlers> <logic > END Bina Nusantara University Optionally atomic Declarations Logic Can contain other compound stmts 8 Variable declaration DECLARE var_name <data type> [ DEFAULT value]; Note: Default value is NULL Examples: DECLARE temp1 SMALLINT DEFAULT 0; DECLARE temp2 INTEGER DEFAULT 10; DECLARE temp3 DECIMAL(10,2) DEFAULT 100.10; DECLARE temp4 REAL DEFAULT 10.1; DECLARE temp5 DOUBLE DEFAULT 10000.1001; DECLARE temp6 BIGINT DEFAULT 10000; DECLARE temp7 CHAR(10) DEFAULT 'yes'; DECLARE temp8 VARCHAR(10) DEFAULT 'hello'; DECLARE temp9 DATE DEFAULT '1998-12-25'; DECLARE temp10 TIME DEFAULT '1:50 PM'; DECLARE temp11 TIMESTAMP DEFAULT '200101-05-12.00.00'; DECLARE Bina Nusantara University temp12 CLOB(2G); DECLARE temp13 BLOB(2G); Assignment statements SET total = 100; ƒ Same as VALUES(100) INTO total; SET total = NULL; ƒ any variable can be set to NULL SET total = (select sum(c1) from T1); ƒ Condition is raised if more than one row SET first_val = (select c1 from T1 fetch first 1 row only) ƒ fetch only the first row from a table SET sch = CURRENT SCHEMA; 9 Example: Stored procedure with parameters CREATE PROCEDURE P2 ( IN v_p1 INT, INOUT v_p2 INT, OUT v_p3 INT) LANGUAGE SQL SPECIFIC myP2 BEGIN -- my second SQL procedure SET v_p2 = v_p2 + v_p1; SET v_p3 = v_p1; END To call the procedure from the Command Editor: call P2 (3, 4, ?) Bina Nusantara University 10 Cursors Cursor declaration and usage: DECLARE <cursor name> CURSOR [WITH RETURN <return target>] FOR <SELECT statement>; OPEN <cursor name>; FETCH <cursor name> INTO <variables> CLOSE <cursor name>; The <return target> value can be to “CLIENT or CALLER” ƒ CLIENT: result set will be returned to the client application ƒ CALLER: result set will be returned to the client or stored procedure that made the call Bina Nusantara University 11 Example: Stored procedure returning result sets CREATE PROCEDURE set () DYNAMIC RESULT SETS 1 LANGUAGE SQL BEGIN DECLARE cur CURSOR WITH RETURN TO CLIENT FOR SELECT name, dept, job FROM staff WHERE salary > 20000; OPEN cur; END Bina Nusantara University 12 Example: Processing a cursor CREATE PROCEDURE sum_salaries(OUT sum INTEGER) LANGUAGE SQL BEGIN DECLARE p_sum INTEGER; DECLARE p_sal INTEGER; DECLARE c CURSOR FOR SELECT SALARY FROM EMPLOYEE; DECLARE SQLSTATE CHAR(5) DEFAULT '00000'; SET p_sum = 0; OPEN c; FETCH FROM c INTO p_sal; WHILE(SQLSTATE = '00000') DO SET p_sum = p_sum + p_sal; FETCH FROM c INTO p_sal; END WHILE; CLOSE c; SET sum = p_sum; END Bina Nusantara University 13 SQLCODE and SQLSTATE Access requires explicit declaration: DECLARE SQLSTATE CHAR(5); DECLARE SQLCODE INT; Can be declared ONLY at outermost scope and automatically set by DB2 after each operation SQLCODE = 0, successful. > 0, successful with warning < 0, unsuccessful = 100, no data was found. i.e. FETCH statement returned no data Bina Nusantara University SQLSTATE Success: SQLSTATE '00000' Not found: SQLSTATE '02000' Warning: SQLSTATE '01XXX' Exception: Everything else 14 Conditions A condition represents a given SQLSTATE It can be raised by any SQL statement You can provide names to a condition to make your code more readable Built-in names for general conditions: SQLWARNING, SQLEXCEPTION, NOT FOUND These map to the SQLSTATEs mentioned in the previous slide Specific conditions: SQLSTATE '01004‘ To assign a user-defined name to a condition: DECLARE truncation CONDITION FOR SQLSTATE '01004' Bina Nusantara University 15 Condition Handling A condition handler must specify • handled conditions • where to resume execution (CONTINUE, EXIT or UNDO) • action to perform to handle the condition Action can be any statement (including control structures) Upon SQLEXCEPTION condition,if no handler exists, the procedure terminates and returns to the client with error raises exception Bina Nusantara University BEGIN [ATOMIC] DECLARE <type> HANDLER FOR <conditions> <handler-action> statement_1; CONTINUE point statement_2; statement_3; END UNDO or EXIT point 16 Flow control statements CASE (selects an execution path (simple / searched)) IF FOR (executes body for each row of table) WHILE ITERATE (forces next iteration. Similar to CONTINUE in C) LEAVE (leaves a block or loop. "Structured Goto") LOOP (infinite loop) REPEAT GOTO RETURN CALL (procedure call) Bina Nusantara University 17 Dynamic SQL Useful when the final form of SQL is known only at RUN TIME Example: if col1 and tabname are variables: 'SELECT ' || col1 || ' FROM ' || tabname; Also recommended for DDL to avoid dependency problems and package invalidation, and to implement recursion. Keywords: ƒ EXECUTE IMMEDATE - ideal for single execution SQL ƒ PREPARE + EXECUTE - ideal for multiple execution SQL Bina Nusantara University 18 Example: Dynamic SQL prerequisite: create table T2 (c1 int, c2 int) CREATE PROCEDURE dyn1 (IN value1 INT, IN value2 INT) SPECIFIC dyn1 BEGIN DECLARE stmt varchar(255); DECLARE st STATEMENT; SET stmt = 'insert into T2 values (?, ?)'; Compile stmt once PREPARE st FROM stmt; Execute it many times EXECUTE st USING value1, value1; EXECUTE st USING value2, value2; SET stmt = 'insert into T2 values (9,9)'; EXECUTE IMMEDIATE stmt; Bina Nusantara University END Compile and execute once 19 Calling from CLI SQLCHAR *stmt = (SQLCHAR *) SQLDOUBLE sal = 20000.0; SQLINTEGER salind = 0; "CALL MEDIAN_RESULT_SET( ? )" ; /* Bound to parameter marker in stmt */ /* Indicator variable for sal */ sqlrc = SQLPrepare(hstmt, stmt, SQL_NTS); sqlrc = SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &sal, 0, &salind); SQLExecute(hstmt); if (salind == SQL_NULL_DATA) printf("Median Salary = NULL\n"); else printf("Median Salary = %.2f\n\n", sal ); sqlrc = StmtResultPrint(hstmt); sqlrc = SQLMoreResults(hstmt); /* Get first result set */ /* Check for another result set */ if (sqlrc == SQL_SUCCESS) { /* There is another result set */ sqlrc = StmtResultPrint(hstmt); } See sqllib/samples/sqlproc/rsultset.c Bina Nusantara University 20 Calling Stored Procedures from a VB.NET Application Try ‘ Create a DB2Command to run the stored procedure Dim procName As String = “TRUNC_DEMO” Dim cmd As DB2Command = conn.CreateCommand() Dim parm As DB2Parameter cmd.CommandType = CommandType.StoredProcedure cmd.CommandText = procName ‘ Register the parm parm.Direction parm parm.Direction output parameters for the DB2Command = cmd.Parameters.Add(“v_lastname”, DB2Type.VarChar) = ParameterDirection.Output = cmd.Parameters.Add(“v_msg”, DB2Type.VarChar) = ParameterDirection.Output ‘ Call the stored procedure Dim reader As DB2DataReader = cmd.ExecuteReader Catch myException As DB2Exception DB2ExceptionHandler(myException) Catch UnhandledExceptionHandler() End Try Bina Nusantara University 21 Calling Stored Procedures from a Java Application try { // Connect to sample database String url = “jdbc:db2:sample”; con = DriverManager.getConnection(url); CallableStatement cs = con.prepareCall(“CALL trunc_demo(?, ?)”); // register the output parameters callStmt.registerOutParameter(1, Types.VARCHAR); callStmt.registerOutParameter(2, Types.VARCHAR); cs.execute(); con.close(); } catch (Exception e) { /* exception handling logic goes here */ } Bina Nusantara University 22 User Defined Function Inline SQL PL SQL PL = SQL Procedural Language Inline SQL PL This is a SQL PL subset supported within a dynamic SQL statement, triggers and UDFs Dynamic compound SQL It means using a BEGIN ATOMIC – END block. The “ATOMIC” part, makes the entire compound SQL be treated as a single UOW (unit of work) Bina Nusantara University 23 Example: Randomly populating a table Pre-req: create sequence myseq@ create table T1 (id bigint, data char(100), insert_ts timestamp)@ Inline SQL PL: begin atomic declare cnt INT default 0; while (cnt < 20000) do insert into t1 values ( nextval for MYSEQ, (select case when (rand() < 0.5) then null else space(int(rand()*100)) end case from sysibm.sysdummy1), current timestamp); set cnt=cnt+1; end while; end @ Bina Nusantara University 24 User-Defined Functions • Functions always return a value • Some built-in functions already exist out-of-the-box – Eg: SUM(), AVG(), DIGITS(), etc. • Can create UDFs in: – SQL PL, C/C++, Java, CLR (Common Language Runtime), and OLE (Object Linking and Embedding) – In this workshop, we focus on SQL PL functions because of their simplicity and popularity Bina Nusantara University 25 Types of functions • Scalar functions – Return a single value – Cannot change database state (i.e. no INSERT, UPDATE, DELETE statements allowed) – Example: COALESCE( ), SUBSTR( ) • Table functions – Return values in a table format – Called in the FROM clause of a query – Can change database state (i.e. allow INSERT, UPDATE, DELETE statements) – Example: SNAPSHOT_DYN_SQL( ), MQREADALL( ) • Others type of functions (not covered in this course): – Row functions – Column functions Bina Nusantara University 26 Scalar function Scalar functions take input values and return a single value They cannot be used to modify table data Example: CREATE FUNCTION deptname(p_empid VARCHAR(6)) RETURNS VARCHAR(30) SPECIFIC deptname BEGIN ATOMIC DECLARE v_department_name VARCHAR(30); DECLARE v_err VARCHAR(70); SET v_department_name = ( SELECT d.deptname FROM department d, employee e WHERE e.workdept=d.deptno AND e.empno= p_empid); SET v_err = 'Error: employee ' || p_empid || ' was not found'; IF v_department_name IS NULL THEN SIGNAL SQLSTATE '80000' SET MESSAGE_TEXT=v_err; END IF; Bina Nusantara University RETURN v_department_name; 27 END Invoking Scalar UDFs • Scalar UDFs can be invoked in SQL statements wherever a scalar value is expected, or in a VALUES clause – SELECT DEPTNAME(‘000010’) FROM SYSIBM.SYSDUMMY1 – VALUES DEPTNAME(‘000010’) Bina Nusantara University 28 Table UDFs • Return a table of rows • Used in the FROM clause of a query • Similar to a view, except more powerful because data modification statements (INSERT/UPDATE/DELETE) can be performed • Typically used to return a table and keep an audit record Bina Nusantara University 29 Table function example A function which enumerates a set of employees of a department CREATE FUNCTION getEnumEmployee(p_dept VARCHAR(3)) RETURNS TABLE (empno CHAR(6), lastname VARCHAR(15), firstnme VARCHAR(12)) SPECIFIC getEnumEmployee RETURN SELECT e.empno, e.lastname, e.firstnme FROM employee e WHERE e.workdept=p_dept Bina Nusantara University 30 Calling a Table function Used in the FROM clause of an SQL statement The TABLE() function must be applied and must be aliased. SELECT * FROM TABLE (getEnumEmployee('E01')) T TABLE() function Bina Nusantara University alias 31 Triggers • A trigger is a database object defined on a table and fired when an INSERT, UPDATE, or DELETE operation is performed. • Activate (“fire”) automatically • Operations that cause triggers to fire are called triggering SQL statements Bina Nusantara University 32 Types of Triggers • BEFORE – activation before row is inserted, updated or deleted – Operations performed by this trigger cannot activate other triggers (i.e. INSERT, UPDATE, and DELETE operations are not permitted) • AFTER – Activated after the triggering SQL statement has executed to successful completion – May activate other triggers (cascading permitted up to 16 levels) • INSTEAD OF – Defined on views – Logic defined in the trigger is executed instead of the triggering SQL statement Bina Nusantara University 33 A Simple BEFORE Trigger define qualifier for new values if no value provided on insert, column is NULL CREATE TRIGGER default_class_end NO CASCADE BEFORE INSERT ON cl_sched REFERENCING NEW AS n FOR EACH ROW MODE DB2SQL WHEN (n.ending IS NULL) SET n.ending = n.starting + 1 HOUR optional WHEN Bina Nusantara University 34 A Simple INSTEAD OF Trigger • It is activated when performing changes to a view • Prereq: CREATE TABLE countries (id int, country varchar(50), region varchar (50), average_temp int) CREATE VIEW view1 (id, continent, temperature) as SELECT id, region, average_temp from countries CREATE TRIGGER update_view1 INSTEAD OF UPDATE ON view1 REFERENCING OLD AS o NEW AS n FOR EACH ROW MODE DB2SQL BEGIN ATOMIC UPDATE countries SET region = n.region WHERE region = o.region; END Bina Nusantara University 35