Appendix B. Inline SQL PL for DB2 UDB for Linux, UNIX, and Windows

From the very first chapter of this book, you have been learning the basics as well as the advanced elements of the SQL Procedural Language. Because this book is the Essential Guide to SQL PL, you will learn everything about SQL PL, including inline SQL PL.

Inline SQL PL is a procedural language that supports a subset of the SQL PL elements. The language is employed by dynamic compound SQL statements that are used in triggers, SQL user-defined functions (UDFs), SQL methods, and stand-alone code. Stand-alone code is also sometimes referred to as SQL PL scripting.

The concept of inline SQL PL is only supported in DB2 LUW for Linux, UNIX, and Windows. In DB2 LUW for iSeries and zSeries, stored procedures, functions, and triggers coded in SQL PL are all compiled into embedded C programs and bound into DB2 as packages.

Dynamic Compound Statement

Inline SQL PL is described as “inline” because the logic is expanded into and executed with the SQL statements that reference them. In this appendix, we look at statements and elements supported in inline SQL PL. For thorough discussions and examples of how it can be used, refer to Chapter 9, “User-Defined Functions and Triggers.”

From the syntax diagram presented in Figure B.1, you can see that the dynamic compound statement must be wrapped inside a BEGIN ATOMIC ... END block. This ensures that either all or none of the statements inside the block will be committed to the database. Optionally, a label can be used to name the atomic block.

Example B.1. Syntax diagram of a dynamic compound statement.

dynamic-compound-statement

>>-+-------------+--BEGIN ATOMIC-------------------------------->
   '-label:------'

>--+-----------------------------------------+------------------>
   | .-------------------------------------. |
   | V                                     | |
   '---+-| SQL-variable-declaration |-+--;-+-'
       '-| condition-declaration |----'


   .-,--------------------------.
   V                            |
>----SQL-procedure-statement--;-+--END--+-------+--------------><
                                        '-label-'

SQL-variable-declaration:


           .-,-----------------.
            V                   |
|--DECLARE----SQL-variable-name-+--data-type-------------------->


   .-DEFAULT NULL------------.
>--+-------------------------+----------------------------------|
   '-DEFAULT--default-values-'


condition-declaration:


|--DECLARE--condition-name--CONDITION--FOR---------------------->

               .-VALUE-.
   .-SQLSTATE--+-------+-.
>--+---------------------+--string-constant---------------------|

In the declaration section, only SQL variable and condition declarations are supported. This means that you cannot declare cursors and condition handlers. You may ask what good is it to declare conditions without the ability to declare handlers. In inline SQL PL, a condition will be useful when you want to raise an error with a SIGNAL statement using a named condition.

As for the SQL procedure statements supported in inline SQL PL, there are few restrictions. Refer to Figure B.2 for a complete list of supported SQL procedure statements.

Example B.2. SQL procedure statements supported in inline SQL PL.

CALL                                  IF
CASE                                  ITERATE
DECLARE <variable>                    LEAVE
DECLARE <condition>                   RETURN
FOR                                   SET
GET DIAGNOSTICS                       SIGNAL
GOTO                                  WHILE

Most of them are fairly straightforward, but a few statements warrant some discussion. The CALL statement enables the ability to CALL stored procedures from within triggers, SQL UDFs, SQL methods, and stand-alone code. This significantly extends the power of these objects and increases the reusability of stored procedures. For example, you can now indirectly handle conditions in an SQL UDF by calling a stored procedure that contains error-handling logic.

Because cursor declaration is not supported in inline SQL PL, cursor manipulations such as positioned updates and deletes are not possible. Rather than using cursors explicitly, you can alternatively use the FOR statement to loop through the result set returned from the specified SELECT statement. Here is an example extracted from Chapter 4, “Using Flow of Control Statements,” that uses a FOR loop to iterate through all the rows returned from the SELECT statement. This method gives you the same result as declaring, opening, and fetching a cursor. In fact, a read-only cursor is declared under the cover when the following example is executed:

Example B.3. An example of a FOR statement extracted from Chapter 4.

FOR v_row AS
    SELECT firstnme, midinit, lastname
      FROM employee
    DO
        SET v_fullname = v_row.lastname || ', ' ||
                         v_row.firstnme || ' ' || v_row.midinit;
        INSERT INTO tname VALUES (v_fullname);
END FOR

The SET statement support in inline SQL PL is slightly different from what it can do inside an SQL procedure. As you may already know, the SET statement is used to assign a value to a variable such as this:

SET v1 = 3;

You can also assign a result value from a SELECT statement to a variable:

SET v_salary = (SELECT salary FROM employee WHERE empno='000010'),

Note that the SELECT statement must return only a single row; otherwise, the statement will raise an error. These statements are both valid in SQL procedures and inline SQL PL. In an SQL procedure, if you want to assign values to one or more variables, you must use the SELECT ... INTO ... statement—for example,

SELECT salary, bonus INTO v_salary, v_bonus FROM employee WHERE empno='000010';

However, in inline SQL PL, the SELECT ... INTO ... statement is not supported. You use the following SET statement to reach the same result instead. Remember that the SELECT statement shown previously must return only one row.

SET v_salary, v_bonus = (SELECT salary, bonus FROM employee WHERE empno='000010'),

To summarize when to use which statement, refer to Table B.1.

Table B.1. Support SET and SELECT ... INTO ... Statements in SQL PL and Inline SQL PL

Sample SQL Statement

Supported in SQL PL

Supported in Inline SQL PL

SET v1 = 3

Y

Y

SET v1 = (SELECT c1 
FROM t1
          FETCH 1 ROW ONLY)

Y

 
           SET v1, v2 = (SELECT c1, c2
              FROM t1
              FETCH 1 ROW ONLY)

N

Y

SELECT c1, c2
INTO v1, v2
FROM t1
FETCH 1 ROW ONLY

Y

N

Besides showing the list of supported statements allowed in inline SQL PL, Figure B.4 calls out the unsupported statements.

Example B.4. SQL procedure statements not supported in inline SQL PL.

ALLOCATE CURSOR                  LOOP
ASSOCIATE LOCATORS               REPEAT
DECLARE <cursor>                 RESIGNAL
DECLARE ... HANDLER              COMMIT
PREPARE                          ROLLBACK
EXECUTE
EXECUTE IMMEDIATE

Looking at Figure B.4, you already know the story about cursors and handlers. Therefore, any statements related to cursors and handlers are not supported.

Because the statements are dynamic, it is rational that the support of the PREPARE, EXECUTE, and EXECUTE IMMEDIATE statements are not needed. As for the LOOP and REPEAT statements, you can use the WHILE loop to implement the same logic. RESIGNAL is not supported because it can only be used within a condition handler for which it is not allowed in inline SQL PL.

Recall that a dynamic compound statement must be atomic so that all or none of the member statements commit successfully. Therefore, it does not make sense to commit or roll back any particular statement inside the block.

Stand-Alone Code

DB2 does support stand-alone codes, also known as SQL PL scripting. It is very straightforward to develop DB2 stand-alone codes because you have just learned about DB2 UDFs and triggers. DB2 stand-alone codes, which are the same as UDFs and triggers, are supported by DB2 inline SQL PL. Figure B.5 shows an example of the DB2 stand-alone code. The example requires a supporting table duplicate_empno, which is defined as the following:

CREATE TABLE duplicate_empno(empno CHAR(6))

Example B.5. An example of DB2 stand-alone code.

BEGIN ATOMIC                                               -- (1)
  DECLARE v_empno CHAR(6);
  DECLARE v_prev_empno CHAR(6);

  FOR c_emp AS                                             -- (2)
    SELECT empno FROM employee ORDER BY empno

  DO
    SET v_empno = empno;

    IF (v_empno = v_prev_empno) THEN                       -- (3)
       INSERT INTO duplicate_empno VALUES (v_empno);
    END IF;

    SET v_prev_empno = v_empno;
  END FOR;
END                                                        -- (4)
@

The example in Figure B.5 is a utility script that can be used to quickly find out the duplicate employee number in the employee table. Assume that the data in the department table is found to be corrupted. For some reason, there are few cases of employees with the same employee ID. The code is used to quickly find the bad employee IDs for further investigation.

A piece of stand-alone code must be encased within the BEGIN ATOMIC and END clause on Lines (1) and (4). An implicit cursor is used with a FOR loop on Line (2). The algorithm to find the duplicate IDs is to sort the IDs first and then compare each ID with the previous ID. All IDs matching their previous IDs are captured on Line (3) for further investigation.

The ’@’ character at the last line is the statement terminator. To execute the code, you need to save it to a file, say find_dup.db2. Then, execute the following at the command prompt:

db2 -td@ -f find_dup.db2

For more information on the statement terminator and on how to execute statements in files, refer to Appendix A, “Getting Started with DB2.”

Please note that there are no duplicate employee numbers in the employee table. You need to manually insert a few rows of bad data in order to capture the duplicate employee numbers.

Choosing Between Dynamic Compound Statements and SQL Procedures

After knowing the differences between inline SQL PL and SQL PL, you are probably wondering when to choose dynamic compound statements as opposed to SQL procedures and vice versa.

First of all, both are compound statements if the SQL procedure contains more than one statement in the procedure body. Using compound statements usually improves performance because statements are grouped in one execution block. This minimizes network flow by sending only one request to DB2 for a set of statements versus one request for each statement.

At SQL procedure creation time, the procedure is compiled and a package is created. The package contains the execution path of how data will be accessed (also known as the data access path). In other words, the optimizer evaluates the best data access path when the procedure is being created. Depending on the query optimization class, the compile time or procedure creation time varies. On the other hand, dynamic compound statements are dynamic in nature, and data access plans are generated at execution time.

Other than understanding when dynamic compound statements and SQL procedures are being compiled, you should also take notice of the complexity of the logic you are implementing. If the logic is complex, we recommend you use SQL procedures because they support the comprehensive SQL PL with which you can easily implement efficient logic.

On other hand, if the logic is simple and the number of statements is relatively small, consider using inline SQL PL instead. With the power of SQL PL, SQL procedures can definitely handle simple logic but use of stored procedures incurs some overhead. In cases when only one or two SQL statements are wrapped inside a stored procedure, there might not be any performance gain. Sometimes it might actually negatively impact performance by using such a stored procedure. In such a case, you can probably obtain better performance results by using inline SQLs.

When inline SQLs are being executed, they are “inlined” into the calling SQL statements. These statements will be expanded to also contain the logic of the compound statements. Therefore, it is always a good practice to keep the inline SQL simple and short so that statement compilation and optimization can be performed efficiently.

Atomicity is also another area to think about. As highlighted in the previous section, commit and rollback are not allowed in dynamic compound statements because they must be atomic. If you need to implement transaction controls inside the compound statements, SQL procedures will be your only choice.

Summary

This appendix introduced you to a subset of SQL PL called inline SQL PL, which is only used by DB2 UDB for Linux, UNIX, and Windows. It is used in dynamic compound SQL statements that can be executed as stand-alone code. Dynamic compound SQL statements can also be used in triggers, SQL UDFs, and SQL methods. Because inline SQL PL does not contain all the SQL PL elements, supported as well as unsupported SQL statements were highlighted. Even though only simple logic is allowed in inline SQL PL, you can extend the power of stored procedures by calling them from within dynamic compound SQL statements.

The appendix explained that utilizing compound statements helps to improve performance. With dynamic compound statements and SQL stored procedures, there are few things to consider when choosing one over the other. First, it is crucial to understand when the data access plan is generated. Secondly, determine whether the complexity of the logic can be handled by dynamic compound statements. If so, pay attention to the size of the SQL statements that are going to be embedded. Use stored procedures if it is large and complex.

A simple example of how to use inline SQL PL in stand-alone code was demonstrated here. For more practical examples of the language usage in UDFs and triggers, Chapter 9, “User-Defined Functions and Triggers,” is a must-read.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.225.220