Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Download as pdf or txt
Download as pdf or txt
You are on page 1of 2

The application declares the size of the structure to the driver with the SQL_ATTR_PARAM_BIND_TYPE statement attribute.

The application binds the


addresses of the parameters in the first structure of the array. Thus, the driver can calculate the address of the data for a particular row and column as

Address = Bound Address + ((Row Number - 1) * Structure Size) + Offset

where rows are numbered from 1 to the size of the parameter set. The offset, if defined, is the value pointed to by the
SQL_ATTR_PARAM_BIND_OFFSET_PTR statement attribute. The following illustration shows how row-wise binding works. The parameters can be placed in
the structure in any order but are shown in sequential order for clarity.

The following code creates a structure with elements for the values to store in the PartID, Description, and Price columns. It then allocates a 10-element
array of these structures and binds it to parameters for the PartID, Description, and Price columns, using row-wise binding. It then executes a statement to
insert 10 rows.

#define DESC_LEN 51
#define ARRAY_SIZE 10

typedef tagPartStruct {
SQLREAL Price;
SQLUINTEGER PartID;
SQLCHAR Desc[DESC_LEN];
SQLINTEGER PriceInd;
SQLINTEGER PartIDInd;
SQLINTEGER DescLenOrInd;
} PartStruct;

PartStruct PartArray[ARRAY_SIZE];
SQLCHAR * Statement = "INSERT INTO Parts (PartID, Description,
Price) "
"VALUES (?, ?, ?)";
SQLUSMALLINT i, ParamStatusArray[ARRAY_SIZE];
SQLULEN ParamsProcessed;

// Set the SQL_ATTR_PARAM_BIND_TYPE statement attribute to use


// column-wise binding.
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_BIND_TYPE, sizeof(PartStruct), 0);

// Specify the number of elements in each parameter array.


SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMSET_SIZE, ARRAY_SIZE, 0);

// Specify an array in which to return the status of each set of


// parameters.
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_STATUS_PTR, ParamStatusArray, 0);

// Specify an SQLUINTEGER value in which to return the number of sets of


// parameters processed.
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &ParamsProcessed, 0);

// Bind the parameters in row-wise fashion.


SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0,
&PartArray[0].PartID, 0, &PartArray[0].PartIDInd);
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, DESC_LEN - 1, 0,
PartArray[0].Desc, DESC_LEN, &PartArray[0].DescLenOrInd);
SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 7, 0,
&PartArray[0].Price, 0, &PartArray[0].PriceInd);

// Set part ID, description, and price.


for (i = 0; i < ARRAY_SIZE; i++) {
GetNewValues(&PartArray[i].PartID, PartArray[i].Desc, &PartArray[i].Price);
PartArray[0].PartIDInd = 0;
PartArray[0].DescLenOrInd = SQL_NTS;
PartArray[0].PriceInd = 0;
}

// Execute the statement.


SQLExecDirect(hstmt, Statement, SQL_NTS);
// Check to see which sets of parameters were processed successfully.
for (i = 0; i < ParamsProcessed; i++) {
printf("Parameter Set Status\n");
printf("------------- -------------\n");
switch (ParamStatusArray[i]) {
case SQL_PARAM_SUCCESS:
case SQL_PARAM_SUCCESS_WITH_INFO:
printf("%13d Success\n", i);
break;

case SQL_PARAM_ERROR:
printf("%13d Error\n", i);
break;

case SQL_PARAM_UNUSED:
printf("%13d Not processed\n", i);
break;

case SQL_PARAM_DIAG_UNAVAILABLE:
printf("%13d Unknown\n", i);
break;

© 2016 Microsoft

Using Arrays of Parameters


To use arrays of parameters, the application calls SQLSetStmtAttr with an Attribute argument of SQL_ATTR_PARAMSET_SIZE to specify the number of sets of
parameters. It calls SQLSetStmtAttr with an Attribute argument of SQL_ATTR_PARAMS_PROCESSED_PTR to specify the address of a variable in which the
driver can return the number of sets of parameters processed, including error sets. It calls SQLSetStmtAttr with an Attribute argument of
SQL_ATTR_PARAM_STATUS_PTR to point to an array in which to return status information for each row of parameter values. The driver stores these addresses
in the structure it maintains for the statement.

Note

In ODBC 2.x, SQLParamOptions was called to specify multiple values for a parameter. In ODBC 3.x, the call to SQLParamOptions has been replaced by
calls to SQLSetStmtAttr to set the SQL_ATTR_PARAMSET_SIZE and SQL_ATTR_PARAMS_PROCESSED_ARRAY attributes.

Before executing the statement, the application sets the value of each element of each bound array. When the statement is executed, the driver uses the
information it stored to retrieve the parameter values and send them to the data source; if possible, the driver should send these values as arrays. Although
the use of arrays of parameters is best implemented by executing the SQL statement with all of the parameters in the array with a single call to the data
source, this capability is not widely available in DBMSs today. However, drivers can simulate it by executing an SQL statement multiple times, each with a
single set of parameters.

Before an application uses arrays of parameters, it must be sure that they are supported by the drivers used by the application. There are two ways to do this:

Use only drivers known to support arrays of parameters. The application can hard-code the names of these drivers, or the user can be instructed to use
only these drivers. Custom applications and vertical applications commonly use a limited set of drivers.

Check for support of arrays of parameters at run time. A driver supports arrays of parameters if it is possible to set the SQL_ATTR_PARAMSET_SIZE
statement attribute to a value greater than 1. Generic applications and vertical applications commonly check for support of arrays of parameters at run
time.

The availability of row counts and result sets in parameterized execution can be determined by calling SQLGetInfo with the
SQL_PARAM_ARRAY_ROW_COUNTS and SQL_PARAM_ARRAY_SELECTS options. For INSERT, UPDATE, and DELETE statements, the
SQL_PARAM_ARRAY_ROW_COUNTS option indicates whether individual row counts (one for each parameter set) are available (SQL_PARC_BATCH) or whether
row counts are rolled up into one (SQL_PARC_NO_BATCH). For SELECT statements, the SQL_PARAM_ARRAY_SELECTS option indicates whether a result set is
available for each set of parameters (SQL_PAS_BATCH) or whether only one result set is available (SQL_PAS_NO_BATCH). If the driver does not allow result
set–generating statements to be executed with an array of parameters, SQL_PARAM_ARRAY_SELECTS returns SQL_PAS_NO_SELECT. It is data source–specific
whether arrays of parameters can be used with other types of statements, especially because the use of parameters in these statements would be data
source–specific and would not follow ODBC SQL grammar.

The array pointed to by the SQL_ATTR_PARAM_OPERATION_PTR statement attribute can be used to ignore rows of parameters. If an element of the array is
set to SQL_PARAM_IGNORE, the set of parameters corresponding to that element is excluded from the SQLExecute or SQLExecDirect call. The array pointed
to by the SQL_ATTR_PARAM_OPERATION_PTR attribute is allocated and filled in by the application and read by the driver. If fetched rows are used as input
parameters, the values of the row status array can be used in the parameter operation array.

Error Processing
If an error occurs while executing the statement, the execution function returns an error and sets the row number variable to the number of the row
containing the error. It is data source–specific whether all rows except the error set are executed or whether all rows before (but not after) the error set are
executed. Because it processes sets of parameters, the driver sets the buffer specified by the SQL_ATTR_PARAMS_PROCESSED_PTR statement attribute to
the number of the row currently being processed. If all sets except the error set are executed, the driver sets this buffer to SQL_ATTR_PARAMSET_SIZE
after all rows are processed.

You might also like