/**********************************************************************
* FILENAME : UsingSelectWithParameterArrays.c
*
* DESCRIPTION :
* Example to illustrate using a SELECT with FOUR parameter markers
* and FOUR parameter arrays
*
* ODBC USAGE :
* SQLSetStmtAttr() - SQL_ATTR_PARAM_BIND_TYPE
* SQL_ATTR_PARAMSET_SIZE
* SQL_ATTR_PARAM_STATUS_PTR
* SQL_ATTR_PARAMS_PROCESSED_PTR
* SQLBindParameter() - to bind the 4 SELECT parameters
* SQLBindCol() - to bind the 4 SELECT columns
* SQLExecDirect() - to execute a SELECT statement
* For each parameter in the param arrays:
* While more data
* SQLFetch() - to retrieve the next result set
* SQLMoreResults() - to initiate the next parameter
* Print Param Status Array
*/
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include "util.c"
/*
* Uses TestTBL1,
*
* PersonID int NOT NULL IDENTITY(1,1),
* FirstName varchar(255) NOT NULL,
* LastName varchar(255),
* Address varchar(255),
* City varchar(255)
*/
#define PARAM_ARRAY_SIZE 10
#define FIRSTNAME_LEN 256
#define LASTNAME_LEN 256
#define ADDRESS_LEN 256
#define CITY_LEN 256
int main () {
SQLHENV henv = SQL_NULL_HENV; // Environment
SQLHDBC hdbc = SQL_NULL_HDBC; // Connection handle
SQLHSTMT hstmt = SQL_NULL_HSTMT; // Statement handle
SQLRETURN retcode;
// Select statement to return person details from TestTBL2
SQLCHAR *stmt = "SELECT FirstName, LastName, Address, City "
"FROM TestTBL2 "
"WHERE FirstName=? AND LastName=? AND Address=? AND City=?";
// Arrays of data
SQLCHAR ArrFirstNames[PARAM_ARRAY_SIZE][2] =
{"a","b","c","d","e","f","g","h","i","j"};
SQLCHAR ArrLastNames[PARAM_ARRAY_SIZE][2] =
{"a","b","c","d","e","f","g","h","i","j"};
SQLCHAR ArrAddress[PARAM_ARRAY_SIZE][2] =
{"a","b","c","d","e","f","g","h","i","j"};
SQLCHAR ArrCity[PARAM_ARRAY_SIZE][2] =
{"a","b","c","d","e","f","g","h","i","j"};
// Column binding variables
SQLCHAR FirstName [FIRSTNAME_LEN];
SQLLEN FirstName_l;
SQLCHAR LastName [LASTNAME_LEN];
SQLLEN LastName_l;
SQLCHAR Address [ADDRESS_LEN];
SQLLEN Address_l;
SQLCHAR City [CITY_LEN];
SQLLEN City_l;
int i;
char * tmp;
char strPersonID[11];
SQLUSMALLINT ParamStatusArray[PARAM_ARRAY_SIZE];
SQLLEN ParamsProcessed=0;
// Allocate the ODBC environment and save handle.
retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_ENV)", henv, SQL_HANDLE_ENV);
// Notify ODBC that this is an ODBC 3.0 app.
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
CHECK_ERROR(retcode, "SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION)",
henv, SQL_HANDLE_ENV);
// Allocate ODBC connection handle and connect.
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_DBC)",
hdbc, SQL_HANDLE_DBC);
// Connect to DATASOURCE
retcode=SQLDriverConnect(hdbc, NULL, "DSN=SQLSRV2014;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
CHECK_ERROR(retcode, "SQLDriverConnect(SQLSRV2014)",
hdbc, SQL_HANDLE_DBC);
// Allocate statement handle.
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_STMT)",
hstmt, SQL_HANDLE_STMT);
// Set parameter set size, status array and params processed pointers
retcode = SQLSetStmtAttr (hstmt, SQL_ATTR_PARAM_BIND_TYPE,
SQL_PARAM_BIND_BY_COLUMN, 0);
retcode = SQLSetStmtAttr (hstmt, SQL_ATTR_PARAMSET_SIZE,
(SQLPOINTER) PARAM_ARRAY_SIZE, 0);
retcode = SQLSetStmtAttr (hstmt, SQL_ATTR_PARAM_STATUS_PTR,
ParamStatusArray, PARAM_ARRAY_SIZE);
retcode = SQLSetStmtAttr (hstmt, SQL_ATTR_PARAMS_PROCESSED_PTR,
&ParamsProcessed, 0);
// Bind array values of parameters 1-4
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR,
SQL_VARCHAR, 2, 0, ArrFirstNames, 2, NULL);
retcode = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR,
SQL_VARCHAR, 2, 0, ArrLastNames, 2, NULL);
retcode = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR,
SQL_VARCHAR, 2, 0, ArrAddress, 2, NULL);
retcode = SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR,
SQL_VARCHAR, 2, 0, ArrCity, 2, NULL);
// Bind columns 1-4
retcode = SQLBindCol(hstmt, 1, SQL_C_CHAR, FirstName,
FIRSTNAME_LEN, &FirstName_l);
retcode = SQLBindCol(hstmt, 2, SQL_C_CHAR, LastName,
LASTNAME_LEN, &LastName_l);
retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, Address,
ADDRESS_LEN, &Address_l);
retcode = SQLBindCol(hstmt, 4, SQL_C_CHAR, City,
CITY_LEN, &City_l);
// execute stmt
retcode = SQLExecDirect (hstmt, stmt, SQL_NTS);
CHECK_ERROR(retcode, "SQLExecDirect()", hstmt, SQL_HANDLE_STMT);
// If you want to look at what is contained on the descriptors,
// un-comment the next line.
// dumpDescriptors ("HSTMT", hstmt, 'Y', 'Y', 1);
// Since the SELECT may find more than one row per parameter set,
// (e.g. match more than one record on 'a,a,a,a' or 'b,b,b,b' etc),
// SQLFetch() is put in a loop until SQL_NO_DATA is returned.
// Without the loop we would only get (at most) one record per parameter
// set because the call to SQLMoreResults() initialises processing for
// the next parameter set (if one exists) and the next call to
// SQLFetch() would then based on that.
do {
retcode=SQL_SUCCESS;
while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLFetch (hstmt);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
printf ("\n - %.10s %.10s %.10s %.10s",
FirstName, LastName, Address, City);
}
}
// We would expect to finish with a status of SQL_NO_DATA
if (retcode != SQL_NO_DATA) {
CHECK_ERROR(retcode, "SQLFetch(SQL_NO_DATA)",
hstmt, SQL_HANDLE_STMT);
}
// MoreResults decides whether there are any more array params to process
// and intiates processing for the next parameter if more exist.
} while (SQLMoreResults(hstmt) == SQL_SUCCESS);
// Check to see which sets of parameters were processed successfully.
printf ("\n\nParameter Status Array :\n");
for (i = 0; i < ParamsProcessed; i++) {
printf(" Parameter Set ");
switch (ParamStatusArray[i]) {
case SQL_PARAM_SUCCESS:
case SQL_PARAM_SUCCESS_WITH_INFO:
printf("%d Success With Info\n", i);
break;
case SQL_PARAM_ERROR:
printf("%d Error\n", i);
break;
case SQL_PARAM_UNUSED:
printf("%d Not processed\n", i);
break;
case SQL_PARAM_DIAG_UNAVAILABLE:
printf("%d Status Unknown\n", i);
break;
}
}
exit:
printf ("\nComplete.\n");
// Free handles
// Statement
if (hstmt != SQL_NULL_HSTMT)
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
// Connection
if (hdbc != SQL_NULL_HDBC) {
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
// Environment
if (henv != SQL_NULL_HENV)
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 0;
}
Further information