Ask the Informix Pro 10-Minute Solution

Writing Procedural Code in Non-Procedural SQL
By Joe Lumbley

The SQL language as implemented by Informix prior to IDS 7.3 is technically a non-procedural language. "Pure" SQL does not include the types of programming statements that programmers use to write computer programs. Such statements as "If-Then," "Do While," and "Case" are not present in SQL. If you are interested in writing procedural code, therefore, the SQL language has not been your tool of choice. Instead, you may have used various workarounds to achieve procedural results.

One method uses Informix's SPL (Stored Procedure Language) to write stored procedures that contain non-procedural elements. Other approaches have included writing embedded SQL code using one of the ESQL products. Still other methods, such as doing multiple SELECTs and UNIONs, can approximate procedural programming, but all of these methods are complex and highly error-prone.

A more common method is to use complex JOIN statement to join parameter tables and return data by SELECTING from the JOINed tables. While these methods do work, they often make it difficult for subsequent programmers to decipher the data flow without good documentation. At worse, future programmers will need to check out the data elements and data contents of multiple tables in order to figure out what the code is doing. Often the more simple, inline code of a procedural language is easier to follow and debug.

With the release of the 7.3X versions of Informix Dynamic Server, you now have several new commands that can simplify your coding jobs and allow you to do some tasks in a simpler, more obvious manner than before.

In this 10-Minute Solution, I'll show you a few of the new expressions and functions supported by IDS 7.3, so you can see how they can make your tasks easier.

CASE Expression
One of the new constructs is the CASE expression. This is an expression that can be selected or manipulated just like all of the other expressions in SQL. The following example uses the "state" table from the stores7 database. This table contains two columns—a "code" column that is a two-character state abbreviation and a "sname" column that contains the name of the state:

SELECT 
    CASE  code
        WHEN 'AK' THEN "Alaska"
        WHEN 'HI'  THEN "Hawaii"
        ELSE "Unknown"
    END,
    code
FROM state
This SQL statement returns:
(expression)	code
Alaska		AK
Hawaii		HI
.........
Here, the CASE expression begins with the word "CASE" and is completed with the word "END." Everything between these two words is an expression that will be returned from the database in the SELECT statement. Notice that because everything from CASE to END is an expression, you need to place a comma after the END if you want to select anything else from the database after the CASE statement.

The system tests for a true condition in each WHEN clause and returns the appropriate value as specified in the THEN clause. The testing of WHEN clauses occurs in the order in which they are presented. In the following example, only the first "AK" is found:

SELECT 
    CASE  code
        WHEN 'AK' THEN "Alaska"
        WHEN 'HI'  THEN "Hawaii"
        WHEN 'AK' THEN "CODE DOES NOT GET HERE"
        ELSE "Unknown"
    END,
    code
FROM state
This SQL statement returns the same result as the first because only the first WHEN 'AK' is executed.

If none of the WHEN clauses is found to be true, the CASE will return the value specified in the ELSE clause. If there's no ELSE clause, it returns null.

The CASE expression is useful in creating and dealing with code tables and lookup tables. For example, suppose that you had a system in which you were creating orders and then using a tax table to calculate applicable taxes, which vary by state. You would have an orders table that includes a code for the state. You would also have a tax table that looks something like this:

CREATE TABLE tax_rate (state_code char(2), tax_percentage integer);
Without using the advanced SQL statements, a simple query to apply sales tax to a transaction would look something like:
SELECT  order.amount, tax_rate,tax_percentage
FROM    order, tax_rate
WHERE   order.state = tax_rate.state_code;
Using the CASE construct, you'd use a statement like this:
SELECT
    Amount, 
    CASE state
        WHEN 'AK' then ".08"
        WHEN 'HI' then ".12"
    END
FROM orders;
This is just an example and you probably wouldn't really hard-code the rates into an application. At this level of simplicity, the JOIN may actually be more readable that the CASE statement. However, as the calculation gets more complex and you have several different situations to consider (e.g., no state tax, other taxes, whether or not taxes are chargeable from your state, whether there's a tax exemption, etc.), the CASE statement begins to be more useful.

DECODE Function
The DECODE statement performs an action similar to the CASE expression mentioned above. DECODE has been around in Oracle for years; it allows the SQL statement to return different results based upon values found in a column. Here's an example:

SELECT code, DECODE(code,
      'AK', "Alaska",
      'AL', "Alabama",
      'CA', "California")
from state
This statement returns:
code    (expression)
AK      Alaska
AL      Alabama
Note that there are several syntactical differences between this and the CASE expression. DECODE is a function, while CASE is an expression. The term "DECODE(whatever...)" serves as a function to return a value from the database. Note that the function body must be enclosed in parentheses.

The term "code" in the segment "DECODE(code...)" refers to the column that is being evaluated—in this instance, the code column. After each code:decoded pair, you need a comma, unlike the CASE statement that doesn't require commas after each WHEN clause.

There are several reasons that you might want to use a DECODE rather than a CASE expression. Although this is just my personal opinion, I think the DECODE format is somewhat more compact and easier to read than the CASE expression. In addition, DECODE is a function handled at the server level, whereas CASE must be parsed first at the client level. This could possibly give DECODE a bit of a performance edge over CASE. On the other hand, if you have a bunch of C programmers in your shop, the CASE statements may be much more familiar and readable. Different strokes. At least we now have the choice.

NVL Function
The NVL (null value) function allows the SQL statement to return more meaningful values when it encounters a null value in the column. For example, assume that a table "member" that has two columns: "name" and "address." Some of the rows do not include an address. The following output results from the SQL statement "SELECT name, address from member;":

name           address
Lumbley        Dallas, Texas
Murchie        Middlebury, Vermont
Mystery Man
Here, Mystery Man does not have an address in the database. To make the output more readable, the following SQL statement uses the NVL function:
SELECT name, NVL(address,"Unlisted Address") as address from member;
This SQL statement returns the following:
name           address
Lumbley        Dallas, Texas
Murchie        Middlebury, Vermont
Mystery Man    Unlisted Address
With the NVL function, if the first argument has a non-null value, this non-null value is returned. If the first argument is null, the second value is returned.
 
Other 10-Minute Solutions
 Writing Procedural Code in Non-Procedural SQL
 Web Access to Informix via ODBC
 Accessing Informix from Microsoft Access
 Database Administration Over the Web: Installing Informix Server Administrator
 Using Informix Server Administrator
 Customizing Informix Server Administrator
 WinSQL: Non-Informix Tools to Access Informix Databases
 Installing and Testing JDBC for Informix Systems
 Using Informix's "First N" Construct in SQL Statements
 Date and Time Manipulation in Informix
 Parsing ASCII Files Elegantly Using SQL
 Hardening Your Informix Database System
 Keeping Your Informix rootdbs Lean and Clean
 Physical Design Issues for Large, Growing Database Systems
 Install and Set Up Server Studio JE for Informix




Sponsored Links


Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map
Jupiterweb networks

internet.comearthweb.comDevx.comClickZ

Search Jupiterweb:

Jupitermedia Corporation has four divisions:
JupiterWeb, JupiterResearch, JupiterEvents, and JupiterImages

Copyright 2004 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Jupitermedia Corporate Info | Newsletters | Tech Jobs | E-mail Offers