Iterators as passed variables for positioned UPDATE or DELETE operations in an SQLJ application
SQLJ allows iterators to be passed between methods as variables.
#sql iterator GeneralIter implements sqlj.runtime.ForUpdate
( String );
public static void main ( String args[] )
{
…
GeneralIter iter1 = null;
#sql [ctxt] iter1 = { SELECT CHAR_COL1 FROM TABLE1 };
GeneralIter iter2 = null;
#sql [ctxt] iter2 = { SELECT CHAR_COL2 FROM TABLE2 };
…
doUpdate ( iter1 );
}
public static void doUpdate ( GeneralIter iter )
{
#sql [ctxt] { UPDATE TABLE1 ... WHERE CURRENT OF :iter };
}
In this example, only one iterator is declared. Two instances of
that iterator are declared, and each is associated with a different
SELECT statement that retrieves data from a different table. During
customization and binding with -staticpositioned YES, SQLJ creates
two DECLARE CURSOR statements, one for each SELECT statement, and
attempts to bind an UPDATE statement for each cursor. However, the
bind process fails with SQLCODE -509 when UPDATE TABLE1 ...
WHERE CURRENT OF :iter
is bound for the cursor for SELECT
CHAR_COL2 FROM TABLE2
because the table for the UPDATE does
not match the table for the cursor.
You can avoid a bind time error for a program like the one in Figure 1 by specifying the bind option SQLERROR(CONTINUE). However, this technique has the drawback that it causes the database manager to build a package, regardless of the SQL errors that are in the program. A better technique is to write the program so that there is a one-to-one mapping between tables in positioned UPDATE or DELETE statements and iterator classes. Figure 2 shows an example of how to do this.
#sql iterator Table2Iter(String);
#sql iterator Table1Iter(String);
public static void main ( String args[] )
{
…
Table2Iter iter2 = null;
#sql [ctxt] iter2 = { SELECT CHAR_COL2 FROM TABLE2 };
Table1Iter iter1 = null;
#sql [ctxt] iter1 = { SELECT CHAR_COL1 FROM TABLE1 };
…
doUpdate(iter1);
}
public static void doUpdate ( Table1Iter iter )
{
…
#sql [ctxt] { UPDATE TABLE1 ... WHERE CURRENT OF :iter };
…
}
public static void doUpdate ( Table2Iter iter )
{
…
#sql [ctxt] { UPDATE TABLE2 ... WHERE CURRENT OF :iter };
…
}
With this method of coding, each iterator class is associated with only one table. Therefore, the data server bind process can always associate the positioned UPDATE statement with a valid iterator.