Static SQL

7.3.1 Static SQL

Static SQL is the most traditional way of building embedded SQL applications. Static SQL applications are designed for scenarios where the applications need to issue the same SQL statements every time it interacts with the database. For example, an application which updates the inventory stock, would always issue the same SQL statement to add

Database Fundamentals 164 new stock. Similarly, an online reservation system would always update the same table

and mark the same column as ‘reserved’ for a new reservation. To get the latest reservation status, it would always issue the same SELECT statement on the same table.

An embedded SQL application where the syntax of the SQL is fully known beforehand and where the SQL statements are hard-coded within the source code of the application is known as a static embedded SQL application. The only input(s) that can be fed to the SQL statements from the application are the actual data values that need to be inserted into the table or the predicate values of the SQL statements. These input values are provided to the SQL statements using host variables.

7.3.1.1 Host variables

Host variables are programming language variables that should only be used for static SQL processing. These host variables need to be declared in the application prior to using them.

A good practice is to initialize them with default values, as soon as they are declared. Another good practice is to append the host variable names with ‘_hv’ to differentiate them from other variables as well as from column names.

Consider the embedded SQL C code snippet shown in Listing 7.1

EXEC SQL SELECT emp_name, emp_dept, emp_salary INTO :name_hv, :dept_hv, :salary_hv FROM employee.details

WHERE emp_id = :id_hv ;

EXEC SQL UPDATE employee.details SET emp_salary = :new_salary_hv WHERE emp_id = :id_hv ;

Listing 7.1 - Embedded SQL C code snippet

In both statements, the table name (employee.details), and the column names (emp_name, emp_dept, etc.) are all hard-coded. The information that can be fed to the SQL statements at runtime are passed using host variables (id_hv, dept_hv, etc.). The colon (:) before each of the host variables is part of the embedded SQL syntax.

7.3.1.2 Embedded SQL application structure

Irrespective of the host language, all embedded SQL applications are comprised of the following three main elements, which are required to setup and execute SQL statements.

 A DECLARE SECTION for declaring host variables.  The main body of the application, which consists of the setup and execution of SQL

statements.  Placements of logic that either commits or rollbacks the changes made by the SQL

statements (if required).

Chapter 7 – Using SQL in an application 165 Listing 7.2 illustrates an embedded SQL C code snippet that demonstrates these three

elements. int getDetails( int employee_id, double new_salary)

{ int ret_code = 1; EXEC SQL INCLUDE SQLCA;

EXEC SQL BEGIN DECLARE SECTION; sqlint32 id_hv = 0; // employee id char name_hv[129] = {0};

// employee name

char dept_hv[129] = {0}; // employee department double salary_hv = 0; // employee salary

EXEC SQL END DECLARE SECTION; // Copy the employee id and salary passed to this function // into the host variables id_hv = employee_id; salary_hv = new_salary;

// Issue the UPDATE statement to set the new salary of an employee EXEC SQL

UPDATE employee.details SET emp_salary = :salary_hv WHERE emp_id = :id_hv;

if (SQLCODE < 0) { printf(“\n UPDATE SQL Error:%ld\n”,SQLCODE); EXEC SQL ROLLBACK; // Rollback the transaction ret_code = 0; // error

} else { EXEC SQL COMMIT; // Commit the transaction

// Issue a SELECT to fetch updated salary information EXEC SQL SELECT emp_name, emp_dept, emp_salary

INTO :name_hv, :dept_hv, :salary_hv FROM employee.details

WHERE emp_id = :id_hv;

if (SQLCODE < 0) {

printf(“\n SELECT SQL Error:%ld\n”,SQLCODE);

Database Fundamentals 166 Ret_code = 0;

} else {

// Display the updated salary information printf(“\n Employee name: %s”,name_hv); printf(“\n Employee Id: %d”,id_hv); printf(“\n Employee Department: %s”,dept_hv); printf(“\n Employee New Salary: Rs. %ld p.a”,salary_hv);

} } return ret_code;

Listing 7.2 - Embedded SQL C code application structure

The above example demonstrated how SQL statements can be embedded in C as a host language. Other host languages like C++, COBOL, Java, and so on also have the same three main elements as described above.

7.3.1.3 SQL communications area, SQLCODE and SQLSTATE

The SQL Communications Area (SQLCA) is a data structure that is used as a communication medium between the database server and its clients. The SQLCA data structure comprises of a number of variables that are updated at the end of each SQL execution. The SQLCODE is one such variable in the data structure which is set to 0 (zero) after every successful SQL execution. If the SQL statement completes with a warning, it is set with a positive, non-zero value; and if the SQL statement returns an error, it is set with

a negative value. SQLCODE values may correspond to either hardware-specific or operating system-specific

issues; for example, when the file system is full, or when there is an error accessing a file. It is a good idea to check for the SQLCODE returned after each SQL execution as shown in the above application.

SQLSTATE is another variable provided in the SQLCA which stores a return code as a string that also indicates the outcome of the most recently executed SQL statement. However, SQLSTATE provides a more generic message that is standardized across different database vendor products.

7.3.1.4 Steps to compile a static SQL application

As discussed earlier, embedded SQL applications need to be pre-compiled first using the DB2 pre-compiler. The pre-compiler checks for SQL statements within the source code, replaces them with equivalent DB2 runtime APIs supported by the host language and re- writes the entire output (with commented SQL statements) into a new file which can then

be compiled and linked using the host language development tools. The DB2 pre-compiler is invoked using the DB2 PRECOMPILE (or PREP) command.

Apart from the SQL replacement, the DB2 pre-compiler performs the following tasks:

Chapter 7 – Using SQL in an application 167

1. It validates the SQL syntax for each coded SQL statement and ensures that appropriate data types are used for host variables by comparing them with their respective column types. It also determines the data conversion methods to be used while fetching or inserting the data into the database.

2. It evaluates references to database objects, creates access plans for them and stores them in a package in the database. An access plan of an SQL statement is the most optimized path to data objects that the SQL statement will reference. The DB2 optimizer estimates these access plans at the time of pre-compilation of the static embedded SQL statement. This estimate is based on the information that is available to the optimizer at the time of the pre-compilation, which is basically fetched from the system catalogs.

Moreover, each application is bound to its respective package residing on the database. The benefit of storing these access plans in the database is that every time the application is run, the access plan for the corresponding SQL statement is fetched from the package and used. This makes SQL execution very fast in the database, since the most optimized way of accessing the required database objects is already known in advance.

At this point, we could also define static SQL statements to be the ones whose access plan can be determined and known in advance and stored in the database

for faster execution. Thus for an SQL statement to be embedded statically in an application, its syntax must be known at pre-compile time.

Once the embedded SQL application is pre-compiled and bound to the database, it can then be compiled and linked using the host language development tools. It is also possible to defer the binding of the application to just before execution. This can be done by

specifying the BINDFILE <bindfile> clause in the PRECOMPILE command, which creates

a bindfile that contains the data required to create a package on a database. This <bindfile> can then be used with the DB2 BIND utility to create a package on the database and bind the application to it. This is also termed as deferred binding.

Figure 7.2 below describes the entire static SQL compilation process. This diagram represents general flow of actions in the compilation process and may be different for a

specific compiler.

Database Fundamentals 168

Figure 7.2 -Static SQL compilation and execution process

For SQLJ applications, similar to the DB2 pre-compiler for embedded SQL applications, the SQLJ translator detects the SQL clauses within the SQLJ application and converts them into JDBC statements. JDBC will be covered in detail in later sections.