9. Using Arrays in Embedded SQL Statements#
Overview#
This chapter explains how to declare and use array-type host variables in embedded SQL statements.
Definition and Declaration#
The term "array host variable" refers to a one-dimensional or two-dimensional array of a data type that can be used as a host variable, that is itself declared for use as a host variable.
One- or two-dimensional arrays can be declared for use with character types and the varchar type, whereas only one-dimensional arrays can be declared for use with other data types. One exception is that an array of pointers cannot be declared.
Examples#
Various examples that illustrate how array host variables are declared are shown below.
[Example 1] The following example shows how to declare character-type and numeric-type arrays as host variables.
< Sample Program : arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
char a_gno[3][10+1];
char a_gname[3][20+1];
char a_goods_location[3][9+1];
int a_stock[3];
double a_price[3];
EXEC SQL END DECLARE SECTION;
[Example 2] The following example shows how to declare an array of structures as a host variable.
< Sample Program: hostvar.h >
EXEC SQL BEGIN DECLARE SECTION;
typedef struct goods
{
char gno[10+1];
char gname[20+1];
char goods_location[9+1];
int stock;
double price;
} goods;
EXEC SQL END DECLARE SECTION;
< Sample Program: arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
goods a_goods[3];
EXEC SQL END DECLARE SECTION;
[Example 3] The following example shows how to declare a structure that contains array elements and use it as a host variable.
< Sample Program: arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
struct
{
char gno[3][10+1];
char gname[3][20+1];
char goods_location[3][9+1];
int stock[3];
double price[3];
} a_goods2;
EXEC SQL END DECLARE SECTION;
Advantages#
Using array-type host variables will have a positive impact on system performance.
The following explanations show how the performance benefits can be achieved.
Compare the use of an array-type host variable with the use of a non-array-type host variables in the execution of an INSERT statement. Suppose for example that it is desired to insert 1000 records. If an array-type host variable having 1000 elements is used, it is only necessary to execute an INSERT statement one time to insert all 1000 records. In contrast, when using a non-array-type host variable, it would be necessary to execute an INSERT statement 1000 times in order to insert all 1000 records. This requires 1000 separate communication events with the database server. It is thus evident that the use of an array-type host variable greatly reduces the consumption of network resources compared to when using a non-array-type host variable.
Now compare the use of an array-type host variable with the use of a non-array-type host variable in the execution of a FETCH statement. In order to fetch 1000 records into an array-type host variable having 1000 elements, it will only be necessary to execute the FETCH statement one time, and all 1000 records will be fetched in sequence into the array, starting with the 0th element. When using a non-array-type host variable, it would be necessary to execute the FETCH statement 1000 times in order to fetch all 1000 records; however, this would not entail a separate communication event with the database server every time the FETCH statement was executed. The reason for this is that internally a certain number of records are retrieved from the database in advance and saved, and every time the FETCH statement is executed, one previously saved record is assigned to the host variable.
This shows that a notable improvement in performance cannot be expected when using array-type host variables to execute a FETCH statement. Only a slight performance improvement, attributable to the decrease in the number of times the FETCH statement is executed, can be expected.
CONNTYPE and Host Array Variables#
CONNTYPE#
The CONNTYPE option is used to determine the method of communication with the database server, and is specified when attempting to establish a connection with the database server. The value of the CONNTYPE option has a strong effect on performance. The magnitude of this effect varies depending on whether array-type host variables are being used.
For information on how to set the CONNTYPE option, please refer to Chapter 6.
Supported Connection Types#
The supported connection types are TCP, UNIX and IPC.
Relationship between CONNTYPE and Host Variable Array Size#
Normally, the IPC connection type realizes the best performance, followed in descending order by the UNIX and TCP connection types. However, when using array-type input host variables, this is not necessarily the case. Therefore, when using array-type input host variables, it is suggested that you test each of the connection methods with various array sizes to determine the combination that yields the best performance in your environment.
Using Host Array Variables in Embedded SQL Statements#
Array-type host variables can be used in embedded SQL statements in various ways.
INSERT#
The array types that can be used with INSERT statements are as follows:
- Simple arrays
- Arrays of structures
- Structures comprising arrays as individual elements thereof
- Extended APRE data types below:
- SQL_DATE_STRUCT
- SQL_TIME_STRUCT
- SQL_TIMESTAMP_STRUCT
- SQL_NUMERIC_STRUCT
Example#
The following example shows the use of an array-type host variable as an input host variable in an INSERT statement.
< Sample Program : arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
char a_gno[3][10+1];
char a_gname[3][20+1];
char a_goods_location[3][9+1];
int a_stock[3];
double a_price[3];
EXEC SQL END DECLARE SECTION;
strcpy(a_gno[0], "X111100001");
strcpy(a_gno[1], "X111100002");
strcpy(a_gno[2], "X111100003");
strcpy(a_gname[0], "XX-201");
strcpy(a_gname[1], "XX-202");
strcpy(a_gname[2], "XX-203");
strcpy(a_goods_location[0], "AD0010");
strcpy(a_goods_location[1], "AD0011");
strcpy(a_goods_location[2], "AD0012");
a_stock[0] = 1000;
a_stock[1] = 1000;
a_stock[2] = 1000;
a_price[0] = 5500.21;
a_price[1] = 5500.45;
a_price[2] = 5500.99;
EXEC SQL INSERT INTO GOODS
VALUES (:a_gno, :a_gname, :a_goods_location,
:a_stock, :a_price);
UPDATE#
The array types that can be used with the UPDATE statement are as follows:
- Simple arrays
- Structures comprising arrays as individual elements
- Extended APRE data types below:
- SQL_DATE_STRUCT
- SQL_TIME_STRUCT
- SQL_TIMESTAMP_STRUCT
- SQL_NUMERIC_STRUCT
Limitation#
If any of the host variables is an array, all host variables must be arrays, and furthermore, the number of elements in each array must be the same. Arrays of structures cannot be used as host variables in the SET or WHERE clause of UPDATE statements. However, it is possible to use an individual element of one structure that is itself one element in an array of structures in the SET or WHERE clause, as shown in the following example:
Example:
EXEC SQL BEGIN DECLARE SECTION;
struct tag1 { int i1; int i2; int i3; } var1[10];
EXEC SQL END DECLARE SECTION;
EXEC SQL UPDATE T1
SET I1 = :var1[0].i1, I2 = :var1[0].i2
WHERE I1 = :var1[0].i3; (O)
Example#
The following example shows the use of an array-type host variable as an input host variable in an UPDATE statement.
< Sample Program: arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
int a_eno[3];
short a_dno[3];
char a_emp_tel[3][15+1];
EXEC SQL END DECLARE SECTION;
a_eno[0] = 10;
a_eno[1] = 11;
a_eno[2] = 12;
a_dno[0] = 2001;
a_dno[1] = 2001;
a_dno[2] = 2001;
strcpy(a_emp_tel[0], "01454112366");
strcpy(a_emp_tel[1], "0141237768");
strcpy(a_emp_tel[2], "0138974563");
EXEC SQL UPDATE EMPLOYEES
SET DNO = :a_dno,
EMP_TEL = :a_emp_tel
WHERE ENO = :a_eno;
DELETE#
The array types that can be used with the DELETE statement are as follows:
- Simple arrays
- Structures comprising arrays as individual elements
- Extended APRE data types below:
- SQL_DATE_STRUCT
- SQL_TIME_STRUCT
- SQL_TIMESTAMP_STRUCT
- SQL_NUMERIC_STRUCT
Limitation#
As in the UPDATE statement, an array of structures cannot be used. One one array element of a structure array can be specified and used as in the example below.
Example:
SQL BEGIN DECLARE SECTION;
struct tag1 { int i1; int i2; int i3; } var1[10];
EXEC SQL END DECLARE SECTION;
EXEC SQL DELETE FROM T1
WHERE I1 = :var1[0].i1 AND
I2 = :var1[0].i2 AND
I3 = :var1[0].i3; (O)
Example#
The following example shows the use of an array-type host variable as an input host variable in a DELETE statement.
< Sample Program: arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
short a_dno[3];
EXEC SQL END DECLARE SECTION;
a_dno[0] = 4001;
a_dno[1] = 4002;
a_dno[2] = 2001;
EXEC SQL DELETE FROM EMPLOYEES
WHERE DNO = :a_dno;
SELECT#
The array types that can be used with the SELECT statement are as follows. The array types listed below can also be used in FETCH statements, and the same limitations apply.
- Simple arrays
- Arrays of structures
- Structures comprising arrays as individual elements
- Extended APRE data types below:
- SQL_DATE_STRUCT
- SQL_TIME_STRUCT
- SQL_TIMESTAMP_STRUCT
- SQL_NUMERIC_STRUCT
Limitation#
If any of the host variables in the INTO clause of a SELECT statement is an array, all of the host variables in the INTO clause must be arrays. Array-type input host variables cannot be used in the WHERE clause of SELECT embedded SQL statements.
Example:
EXEC SQL BEGIN DECLARE SECTION;
int var1;
int var2[10];
int var3[10];
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT * INTO :var1
FROM T1 WHERE i1 = :var3; (X)
또는
EXEC SQL SELECT * INTO :var2
FROM T1 WHERE i1 = :var3; (X)
If the number of records that are returned is greater than the size of the array, an error indicating that too many rows were returned will be raised.
Example#
The following example shows the use of an array-type host variable as an output host variable in a SELECT statement. Note that the input host variable is not an array.
< Sample Program : arrays2.sc >
EXEC SQL BEGIN DECLARE SECTION;
short s_dno;
short a_dno[5];
char a_dname[5][30+1];
char a_dep_location[5][9+1];
EXEC SQL END DECLARE SECTION;
s_dno = 3000;
EXEC SQL SELECT DNO, DNAME, DEP_LOCATION
INTO :a_dno, :a_dname, :a_dep_location
FROM DEPARTMENTS
WHERE DNO > :s_dno;
FOR Clause#
Sometimes, it is desired to process only some of the array elements in an embedded SQL statement that uses an array-type input host variable. For example, when using an array-type input host variable to fetch data and then insert the fetched data back into the database using the same host variable, the number of fetched data items may be smaller than the size of the array. In such cases, the number of elements to be inserted can be set using a FOR clause.
The FOR clause plays the role of determining the number of array elements to process when using an array-type input host variable. FETCH statements can only be made using output host variables.
When using a FOR clause, it takes priority over the size of the array-type host variable in determining the number of array elements that are processed. For example, when the size of a host variable array is 10 and the number of array elements to be processed, as specified by a FOR clause, is 5, only five of the elements in the array-type host variable, namely the 0th to 4th elements, will be processed.
The use of the FOR clause is particularly convenient in situations where the number of array elements to process changes every time the embedded SQL statement is executed.
FOR clauses can be used with the following kinds of embedded SQL statements:
- INSERT
- UPDATE
- DELETE
- FETCH
Syntax#
EXEC SQL FOR <:host_var | constant> { INSERT … | UPDATE … | DELETE …| FETCH …}
Arguments#
- <:host_var>
This is used to set the number of array elements to be processed. host_var does not need to be declared in the host variable declaration section. - <constant>
This is used to set a fixed number of array elements to be processed.
Note:#
The value specified in the FOR clause must be at least one.
Example:
EXEC SQL BEGIN DECLARE SECTION;
int cnt;
int var1[10];
int var2[10];
EXEC SQL END DECLARE SECTION;
cnt = 5; (O)
EXEC SQL FOR :cnt INSERT INTO T1 VALUES (:var1, :var2);
cnt = 0; (X)
EXEC SQL FOR :cnt INSERT INTO T1 VALUES (:var1, :var2);
cnt = -1; (X)
EXEC SQL FOR :cnt INSERT INTO T1 VALUES (:var1, :var2);
Examples#
Examples of the use of FOR clauses in various kinds of SQL statements follow.
[Example 1] The following example shows the use of a FOR clause in an INSERT statement. The number of array elements to be processed is determined by the host variable cnt in the FOR clause, and thus only the 0th and 1st elements in the a_goods array are inserted into the GOODS table.
< Sample Program: hostvar.h >
EXEC SQL BEGIN DECLARE SECTION;
typedef struct goods
{
char gno[10+1];
char gname[20+1];
char goods_location[9+1];
int stock;
double price;
} goods;
EXEC SQL END DECLARE SECTION;
< Sample Program: arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
goods a_goods[3];
int cnt;
EXEC SQL END DECLARE SECTION;
cnt = 2;
EXEC SQL FOR :cnt INSERT INTO GOODS VALUES (:a_goods);
[Example 2] The following example shows the use of a FOR clause in an UPDATE statement. The number of array elements to be processed is constant (2), and thus only two elements, starting with the 0th element, will be processed. That is, the dno and emp_tel columns in the records in the employees table for which the value in the eno column matches the first two values of a_employee.eno will be respectively updated with the 0th and 1st elements of a_employee.dno and a_employee.emp_tel.
< Sample Program: arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
struct
{
int eno[3];
short dno[3];
char emp_tel[3][15+1];
} a_employee;
EXEC SQL END DECLARE SECTION;
EXEC SQL FOR 2 UPDATE EMPLOYEES
SET DNO = :a_employee.dno,
EMP_TEL = :a_employee.emp_tel,
JOIN_DATE = SYSDATE
WHERE ENO = :a_employee.eno;
[Example 3] The following example shows how to use the FOR clause in a DELETE statement. The number of array elements to be processed is specified using the host variable cnt, and only two arrays from the 0th array are processed. That is, only the 0th and 1st records of a_dno are deleted.
< Sample Program : arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
short a_dno[3];
int cnt;
EXEC SQL END DECLARE SECTION;
cnt = 2;
EXEC SQL FOR :cnt DELETE FROM EMPLOYEES WHERE DNO = :a_dno;
[Example 4] The following example shows how to use the FOR clause in a FETCH statement. The number of array elements to be processed is specified using the host variable cnt, and two data are obtained from the 0th array.
< Sample Program: cursor2.sc >
EXEC SQL BEGIN DECLARE SECTION;
/* declare array output host variables */
int a_eno[ARRAY_SIZE];
short a_dno[ARRAY_SIZE];
double a_salary[ARRAY_SIZE];
/* declare input host variables */
double s_salary;
/* declare indicator variables */
SQLLEN a_eno_ind[ARRAY_SIZE];
SQLLEN a_dno_ind[ARRAY_SIZE];
SQLLEN a_salary_ind[ARRAY_SIZE];
int count;
EXEC SQL END DECLARE SECTION;
count = 2;
/* Using with FOR clause */
printf("FOR %d FETCH Result\n", count);
EXEC SQL FOR :count FETCH EMP_CUR
INTO :a_eno :a_eno_ind,
:a_dno :a_dno_ind,
ATOMIC FOR Clause#
When the ATOMIC FOR Clause is used with an array-type input host variable in an embedded SQL statement, multiple iterations of the statement corresponding to each of the array elements are combined and processed all at the same time using so-called "Atomic Array Insert".
Therefore, when using ATOMIC FOR, if the execution of even one of the iterations fails, then the execution of the entire statement fails. The individual resultant values are never written to disk or shared with other processes. That is, either none of the values are inserted, or all of them are inserted.
[Figure 9-1] Values Resulting from Array Insert and Atomic Array Insert Operations
While "Non-Atomic Array Insert" (i.e. the use of an array input host variable with an INSERT embedded SQL statement) already offers the advantage of reduced communication costs, Atomic Array Insert increases performance even further, because it reduces the number of statements that must be executed.
The following table compares Array Insert and Atomic Array Insert.
Assortment | Array Insert | Atomic Array Insert |
---|---|---|
Number of Statement Executions | Number of Array Elements | One |
Number of Resultant Values | Number of Array Elements | One |
Speed | Fast | Very Fast |
[Table 9-1] Difference between Array Insert and Atomic Array Insert
Syntax#
EXEC SQL ATOMIC FOR <:host_var | constant> {INSERT … }
Arguments#
- <:host_var>
This is used to set the number of array elements to be processed. This variable doesn't have to be declared in the host variable declaration section. - <constant>
This is used to set a fixed number of array elements to be processed.
Notes:#
The ATOMIC FOR clause can only be used with INSERT statements. It cannot be used with any other DML statements.
The ATOMIC FOR clause can be used with INSERT statements in which data are inserted into LOB type columns, but once the LOB data have been transferred, they cannot be rolled back if an error occurs. In such cases it will be necessary for the user to roll back the LOB data directly using a savepoint.
There are several other considerations to keep in mind when using the ATOMIC FOR clause, which are set forth in the following table:
Array Insert | Atomic Array Insert | |
---|---|---|
Foreign Key | Operates Normally | Operates Normally |
Unique Key | Operates Normally | Operates Normally |
Not NULL | Operates Normally | Operates Normally |
Check Constraint | Operates Normally | Operates Normally |
Trigger Each Row | Executed N times | Executed N times |
Trigger Each Statement | Executed N times | Executed once |
Partitioned Table | Operates Normally | Operates Normally |
Sequence | Executed N times | Executed N time |
SYSDATE | Executed N times | Executed once |
LOB Column | Operates Normally | Atomicity cannot be guaranteed when an error occurs |
Procedure | Operates Normally | Operates Normally |
When a INSERT statement contains a subquery | A new view for the subquery is created N times | The view corresponding to the first execution is reused |
[Table 9-2] Restrictions on Atomic Array Insert
Example#
EXEC SQL ATOMIC FOR 20 INSERT INTO T1 VALUES( :data );
ONERR Clause#
Using this clause with an embedded SQL statement that uses an array-type input host variable enables detection of whether execution corresponding to each of the array elements was successful. This makes it possible to manage the list of elements for which execution failed by defining some management tasks that use DML statements.
Syntax#
EXEC SQL ONERR <:ret_code, :err_code>
{INSERT | UPDATE | DELETE}
or
EXEC SQL ONERR <:ret_code, :err_code >
FOR <:cnt | constant> {INSERT | UPDATE | DELETE}
Arguments#
- <:ret_code, :err_code>
The result of execution of the SQL statement is saved in the first host variable, ret_code. This variable must be declared as a pointer to an array of short. The error code is saved in the second host variable, err_code. This variable must be declared as a pointer to an array of int. - <:cnt>
This value is used to specify the number of array elements to be processed. This variable doesn't have to be declared in the host variable declaration section. - <constant>
This value is used to specify a fixed number of array elements to be processed.
Restrictions#
- The array-type host variables used in the ONERR clause, ret_code and err_code, must not be smaller than any of the arrays used in the SQL statement.
- When using the ONERR clause together with the FOR clause, the size of the array-type host variable used in the ONERR clause must not be less than cnt, that is, the number of array elements to be processed.
Example#
EXEC SQL ONERR :err_rc , :err_code
UPDATE T1 SET c2 = c2+1 WHERE c1 = :var1;
EXEC SQL ONERR :err_rc , :err_code FOR :arr_count
UPDATE T1 SET c2 = c2+1 WHERE c1 = :var1;
sqlca.sqlerrd#
When using an array-type host variable in an embedded SQL statement, the value of the sqlca.sqlerrd variable can be checked after execution of the embedded SQL statement.
This section explains the meaning of the contents that can be stored in the sqlca.sqlerrd variable.
sqlca.sqlerrd[2]#
When using non-array type host variables, this value can be checked after executing UPDATE and DELETE statements.
When using array type host variables, this value can be checked after executing INSERT, UPDATE, DELETE, and SELECT statements.
When the value stored in the sqlca.sqlcode variable is SQL_SUCCESS, the meaning of the value stored in the sqlca.sqlerrd[2] variable varies depending on the kind of embedded SQL statement that was executed. The following describes the meaning for each kind of embedded SQL statement.
INSERT#
When not using an array type input host variable, the value of sqlca.sqlerrd[2] will be 1 after successful execution of an INSERT statement. This means simply that one record has been inserted.
For example, if an INSERT statement is executed using a host variable of which the array size is 3, and the insertion operations corresponding to all three array elements are successful, then three records will be inserted, and the value stored in sqlca.sqlerrd[2]will be 3. If the insertion operations corresponding to the first two array elements are successful but the insertion operation corresponding to the third array element fails, then two records will be inserted, and this value will be 2.
However, the value stored in sqlca.sqlerrd[2] is somewhat different when using Atomic Array Insert. If the Atomic Array Insert operation is completely successful, this value will be equal to the number of rows that were inserted, i.e. the number of array elements, but if even one insertion operation fails, this value will be 0.
UPDATE/DELETE#
After a successful UPDATE or DELETE operation, the number of updated or deleted records will be stored in sqlca.sqlerrd[2].
Because there can be more than one record that meets a condition specified using each element of an array-type host variable, this value may be higher than the array size.
For example, assume that you have performed an UPDATE operation using an array-type host variable having three elements, and that the operation was successful for each of the three array elements. If there were three records that satisfied the condition when using the 0th element, two records that satisfied the condition when using the 1st element, and no records that satisfied the condition when using the 2nd element, a total of five records would be updated, so the value stored in sqlca.sqlerrd[2] would be 5.
SELECT/FETCH#
If the output host variable is not an array-type host variable, this value will be meaningless, i.e. a garbage value.
If the output host variable is an array-type host variable, the number of records that have been selected (or fetched) at the present moment in time will be stored in sqlca.sqlerrd[2]. Note that this value is not the cumulative number of records fetched using multiple FETCH statements. It is only the number of records that have been fetched by the current statement. Therefore, a value larger than the size of the array will never be observed.
If the number of records that were returned is the same as or smaller than the array size, then the value stored in sqlca.sqlcode will be SQL_SUCCESS, and the number of records that were returned will be stored in sqlca.sqlerrd[2].
If no records were returned, the value stored in sqlca.sqlcode will be SQL_NO_DATA, and zero (0) will be stored in sqlca.sqlerrd[2].
For example, assume that you have performed a SELECT operation using an array-type output host variable having ten (10) elements. If there were five records that met the conditions, those five records would be stored in the output host variable in sequence, starting with the 0th element. At this time, the value of sqlca.sqlcode would be SQL_SUCCESS, and 5 would be stored in sqlca.sqlerrd[2].
sqlca.sqlerrd[3]#
After the execution an embedded SQL statement using an array-type input host variable, this variable 배열 stores the number of array elements for which execution was successful, regardless of whether the statement is an INSERT, UPDATE, or DELETE statement. Therefore, a value larger than the size of the array will never be observed. If the value of sqlca.sqlcode is SQL_SUCCESS, the value of the sqlca.sqlerrd[3] variable will be equal to the size of the array.
All of the following conditions must be met in order for this variable to contain a meaningful value:
- This value must be checked only after the execution of an embedded SQL statement using an array-type input host variable.
- The statement that was just executed before checking this value must be an INSERT, UPDATE, or DELETE SQL statement, or a stored procedure.
When using Atomic Array Insert, if the Atomic Array Insert operation is completely successful, this value will be 1, but if even one insertion operation fails, this value will be 0.
Example#
For example, if an UPDATE statement is executed using a host variable of which the array size is 3, and the update operations corresponding to the 0th and 1st array elements are successful but no records are updated by the UPDATE operation corresponding to the 2nd array element, then the value returned in sqlca.sqlcode will not be SQL_SUCCESS and the value returned in sqlca.sqlerrd[3] will be 2. If there were three records that satisfied the condition when using the 0th element and two records that satisfied the condition when using the 1st element, a total of five records would be updated, so the value stored in sqlca.sqlerrd[2] would be 5.
Notes#
- Unless the value of sqlca.sqlcode is SQL_SUCCESS, the value stored in the sqlca.sqlerrd[2] variable will have no meaning (i.e. will be a garbage value). Therefore, check the value of the sqlca.sqlerrd[2] variable only when the value of sqlca.sqlcode is SQL_SUCCESS.
- When using an array-type host variable in AUTOCOMMIT mode, a "transaction" is not the totality of operations performed using the entire array. Rather, each of the operations corresponding to a single array element is one transaction. Therefore, the changes effected by each of the successful operations corresponding to individual array elements are permanently stored in the database, even if the operations corresponding to some of the other array elements fail.
For example, if an INSERT statement is executed using a host variable of which the array size is 3, and the insertion operations corresponding to the first two array elements are successful but the insertion operation corresponding to the last array element fails, then two records will be permanently inserted into the table.
Limitations on the Use of Array-Type Host Variables#
There are several factors that limit the use of arrays as host variables. Please keep the following in mind when writing applications
In the DECLARE section#
-
Host variables in pointer arrays cannot be declared or used in embedded SQL statements.
Example:
EXEC SQL BEGIN DECLARE SECTION; char *var1[10]; (X) EXEC SQL END DECLARE SECTION;
-
Only single-dimensional arrays can be used as host variables. The exception is that two-dimensional arrays are allowed for the char and varchar types.
Example of acceptable usage:
EXEC SQL BEGIN DECLARE SECTION; char var1[10][10]; int var2[10]; EXEC SQL END DECLARE SECTION;
Example of unacceptable usage:
EXEC SQL BEGIN DECLARE SECTION; char var3[10][10][10]; int var4[10]10]; EXEC SQL END DECLARE SECTION;
In SQL Statements#
Arrays cannot be used as input host variables in SELECT statements and cursor-related statements.
Example:
EXEC SQL BEGIN DECLARE SECTION;
int var1[10];
int var2[10];
int var3[10];
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT I1, I2 INTO :var1, :var2
FROM T1 WHERE I1 = :var3; (X)
Structures and Arrays#
Both arrays of structures and structures containing arrays as constituent elements thereof can be declared and used as host variables.
Arrays of Structure#
The following explains how to declare arrays of structures and use them.
Advantages#
- The use of an array of structures is convenient when using an INSERT statement to insert multiple records into all of the columns in a table.
- Similarly, it is convenient to use an array of structures when using a SELECT or FETCH statement to retrieve multiple records from all of the columns in a table.
Disadvantages#
- Because an indicator variable cannot be specified for use with an array of structures, it is impossible to use an array of structures when any of the values to be input, or any of the values to be retrieved using a SELECT or FETCH statement, are NULL.
Limitations#
-
Since two-dimensional arrays are not allowed, when using an array of structures, the components of that structure cannot be arrays.
Example:
EXEC SQL BEGIN DECLARE SECTION; struct tag1 { int i1[10]; int i2[10]; } var1[10]; (X) EXEC SQL END DECLARE SECTION;
-
When using an array of structures as an output host variable in the INTO clause of a SELECT or FETCH statement, only one output host variable can be used. In other words, the array of structures cannot be used with any other output host variables. Therefore, if the host variable to be used in the INTO clause of a SELECT or FETCH statement is an array of structures, the number of elements in the structure must be the same as the number of columns in the select list.
Similarly, when using an array of structures as an input host variable in the VALUES clause of an INSERT statement, only one input host variable can be used. In other words, the array of structures cannot be used with any other input host variables. Therefore, if the host variable to be used in the VALUES clause of an INSERT statement is an array of structures, the number of elements in the structure must be the same as the number of columns specified in the INSERT statement.
The foregoing two limitations are due to an internal rule that requires the structure to include all host variables when the host variable is an array of structures.
Example:
EXEC SQL BEGIN DECLARE SECTION;
struct tag1 { int i1; int i2; } var1[10];
struct tag1 { int i3; int i4; } var2[10];
int var3;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT I1, I2 INTO :var1
FROM T1 WHERE I1 = :var3; (O)
EXEC SQL SELECT I1, I2, I3, I4 INTO :var1, :var2
FROM T1 WHERE I1 = :var3; (X)
An indicator variable cannot be specified for use with a host variable that is an array of structures. Therefore, when an array of structures is used as an output host variable, it must be guaranteed that no NULL values will be returned.
Example:
EXEC SQL BEGIN DECLARE SECTION;
struct tag1 { int i1; int i2; char i3[10]; } var1[10];
struct tag2 { int i1_ind; int i2_ind; int i3_ind; } var1_ind[10];
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT * INTO :var1 :var1_ind; (X)
Examples#
Various examples of the declaration and use of arrays of structures as host variables are shown below.
[Example 1] The following example shows the use of an array of structures as an input host variable in an INSERT statement.
< Sample Program: hostvar.h >
EXEC SQL BEGIN DECLARE SECTION;
typedef struct goods
{
char gno[10+1];
char gname[20+1];
char goods_location[9+1];
int stock;
double price;
} goods;
EXEC SQL END DECLARE SECTION;
< Sample Program: arrays1.sc >
/* specify path of header file */
EXEC SQL OPTION (INCLUDE=./include);
/* include header file for precompile */
EXEC SQL INCLUDE hostvar.h;
EXEC SQL BEGIN DECLARE SECTION;
goods a_goods[3];
EXEC SQL END DECLARE SECTION;
strcpy(a_goods[0].gno, "Z111100001");
strcpy(a_goods[1].gno, "Z111100002");
strcpy(a_goods[2].gno, "Z111100003");
strcpy(a_goods[0].gname, "ZZ-201");
strcpy(a_goods[1].gname, "ZZ-202");
strcpy(a_goods[2].gname, "ZZ-203");
strcpy(a_goods[0].goods_location, "AD0020");
strcpy(a_goods[1].goods_location, "AD0021");
strcpy(a_goods[2].goods_location, "AD0022");
a_goods[0].stock = 3000;
a_goods[1].stock = 4000;
a_goods[2].stock = 5000;
a_goods[0].price = 7890.21;
a_goods[1].price = 5670.45;
a_goods[2].price = 500.99;
EXEC SQL INSERT INTO GOODS VALUES (:a_goods);
[Example 2] The following example shows the use of an array of structures as an output host variable in a SELECT statement.
< Sample Program: hostvar.h >
EXEC SQL BEGIN DECLARE SECTION;
typedef struct department
{
short dno;
char dname[30+1];
char dep_location[9+1];
int mgr_no;
} department;
EXEC SQL END DECLARE SECTION;
< Sample Program: arrays2.sc >
/* specify path of header file */
EXEC SQL OPTION (INCLUDE=./include);
/* include header file for precompile */
EXEC SQL INCLUDE hostvar.h;
EXEC SQL BEGIN DECLARE SECTION;
short s_dno;
department a_department[5];
EXEC SQL END DECLARE SECTION;
s_dno = 2000;
EXEC SQL SELECT * INTO :a_department
FROM DEPARTMENTS WHERE DNO < :s_dno;
Structures Containing Arrays#
The following explains how to declare and use structures containing arrays as constituent elements.
Advantages#
- The use of a structure containing arrays is convenient when using an INSERT statement to insert multiple records into all of the columns in a table.
- Similarly, it is convenient to use a structure containing arrays when using a SELECT or FETCH statement to retrieve multiple records from all of the columns in a table.
- Because indicator variables can be specified for use with structures containing arrays, it is possible to handle NULL values.
- Because it is possible to specify the individual elements of structures as host variables, structures containing arrays can be used in UPDATE statements and in the WHERE clauses of SELECT, UPDATE, and DELETE statements.
- The limitation on the use of arrays of structures as host variables, stating that the array of structures must be the only host variable in the input or output host variable list, does not also apply to the use of structures containing arrays as constituent elements. When a structure containing one or more arrays is used as a host variable, there is no requirement that the structure be the only input or output host variable. That is, structures containing arrays can be freely used together with other host variables in the input host variable list or output host variable list
Example#
Various examples of the declaration and use of structures containing arrays as host variables are shown below.
[Example 1] The following example shows the use of a structure containing arrays as an input host variable in an UPDATE statement. Because the value SQL_NULL_DATA is set in the elements of the a_emp_tel_ind array, the values in the EMP_TEL column will be overwritten with NULL.
< Sample Program : arrays1.sc >
EXEC SQL BEGIN DECLARE SECTION;
struct
{
int eno[3];
short dno[3];
char emp_tel[3][15+1];
} a_employee;
int a_emp_tel_ind[3];
EXEC SQL END DECLARE SECTION;
/* set host variables */
a_employee.eno[0] = 17;
a_employee.eno[1] = 16;
a_employee.eno[2] = 15;
a_employee.dno[0] = 1003;
a_employee.dno[1] = 1003;
a_employee.dno[2] = 1003;
/* set indicator variables */
a_emp_tel_ind[0] = SQL_NULL_DATA;
a_emp_tel_ind[1] = SQL_NULL_DATA;
a_emp_tel_ind[2] = SQL_NULL_DATA;
EXEC SQL UPDATE EMPLOYEES
SET DNO = :a_employee.dno,
EMP_TEL = :a_employee.emp_tel :a_emp_tel_ind,
JOIN_DATE = SYSDATE
WHERE ENO > :a_employee.eno;
[Example 2] The following example shows the use of a structure containing arrays as an output host variable in a SELECT statement.
< Sample Program: arrays2.sc >
EXEC SQL BEGIN DECLARE SECTION;
short s_dno;
struct
{
short dno[5];
char dname[5][30+1];
char dep_location[5][9+1];
int mgr_no[5];
} a_department2;
EXEC SQL END DECLARE SECTION;
s_dno = 2000;
EXEC SQL SELECT * INTO :a_department2
FROM DEPARTMENTS WHERE DNO < :s_dno;
Sample Programs#
arrays1.sc#
This sample can be found at $ALTIBASE_HOME/sample/APRE/arrays1.sc.
Result of Execution#
$ is -f schema/schema.sql
$ make arrays1
$ ./arrays1
<ARRAYS 1>
------------------------------------------------------
[Scalar Array Host Variables With Insert]
------------------------------------------------------
3 rows inserted
3 times insert success
------------------------------------------------------
[Structure Array Host Variables With Insert]
------------------------------------------------------
3 rows inserted
3 times insert success
------------------------------------------------------
[Arrays In Structure With Insert]
------------------------------------------------------
3 rows inserted
3 times insert success
------------------------------------------------------
[Error Case : Array Host Variables With Insert]
------------------------------------------------------
SQLCODE : -69720
sqlca.sqlerrm.sqlerrmc : [ROW-2] ERR-11058(23000) : The row already exists in a unique index.
[ROW-3] ERR-11058(23000) : The row already exists in a unique index.
1 rows inserted
1 times insert success
------------------------------------------------------
[Scalar Array Host Variables With Update]
------------------------------------------------------
3 rows updated
3 times update success
------------------------------------------------------
[Arrays In Structure With Update]
------------------------------------------------------
12 rows updated
3 times update success
------------------------------------------------------
[Scalar Array Host Variables With Delete]
------------------------------------------------------
6 rows deleted
3 times delete success
------------------------------------------------------
[For Clause With Insert]
------------------------------------------------------
2 rows inserted
2 times insert success
------------------------------------------------------
[For Clause With Update]
------------------------------------------------------
2 rows updated
2 times update success
------------------------------------------------------
[For Clause With Delete]
------------------------------------------------------
3 rows deleted
2 times delete success
arrays2.sc#
This sample can be found at $ALTIBASE_HOME/sample/APRE/arrays2.sc.
Result of Execution#
$ is -f schema/schema.sql
$ make arrays2
$ ./arrays2
<ARRAYS 2>
------------------------------------------------------
[Scalar Array Host Variables With Select]
------------------------------------------------------
DNO DNAME DEP_LOCATION
------------------------------------------------------
3001 CUSTOMER SUPPORT DEPT London
3002 PRESALES DEPT Peking
4001 MARKETING DEPT Seoul
4002 BUSINESS DEPT LA
4 rows selected
------------------------------------------------------
[Structure Array Host Variables With Select]
------------------------------------------------------
DNO DNAME DEP_LOCATION MGR_NO
------------------------------------------------------
1001 RESEARCH DEVELOPMENT DEPT 1 New York 16
1002 RESEARCH DEVELOPMENT DEPT 2 Sydney 13
1003 SOLUTION DEVELOPMENT DEPT Japan 14
3 rows selected
------------------------------------------------------
[Arrays In Structure With Select]
------------------------------------------------------
DNO DNAME DEP_LOCATION MGR_NO
------------------------------------------------------
1001 RESEARCH DEVELOPMENT DEPT 1 New York 16
1002 RESEARCH DEVELOPMENT DEPT 2 Sydney 13
1003 SOLUTION DEVELOPMENT DEPT Japan 14
3 rows selected
------------------------------------------------------
[Error Case : Array Host Variables]
------------------------------------------------------
Error : [-594092] Returns too many rows
------------------------------------------------------
[Execute Procedure With Array In-Binding]
------------------------------------------------------
Success execute procedure