ODBC drivers >

JDBC drivers >

Bridges, gateways >

Other >

All products

Connect JDBC to any ODBC driver

Connect JDBC to Microsoft Access

Cross-platform or cross-architecture access to any ODBC driver

ODBC access to any JDBC driver

Connect dbExpress applications to any ODBC driver

Connect XML applications to any ODBC driver

Access mutiple ODBC data sources from one SQL statement

Create custom ODBC drivers

Bespoke data access requirements

In the pipeline

Support

Resources

Quick start

Licensing

Knowledge Base

User Guides

Company

About Us

Careers & Partners

Download ODBC Drivers for

Oracle, SQL Server, Salesforce, MongoDB, Access, Derby, InterBase, DB2, & more.

Learn More
/**********************************************************************
* FILENAME : WritingMultipleLongTextFields.c
*
* DESCRIPTION :
* Example mainly illustrates use of SQLPutData () to insert record
* with 'text' fields uses either TestTBL3 (one text field) or
* TestTBL4 (two text fields) in chunks which are requested at
* execute time thus illustrating DAE and how long text fields
* are handled.
*
* Can also be used to insert records into two other tables used
* for testing, TestTBL1 and TestTBL2, which do not have text fields.
*
* ODBC USAGE :
*
* Asks user to select table (1, 2 3 or 4)
* SQLPrepare () - to prepare statement for selected table
* SQLNumParams () - to establish how many parameters are needed
* Asks for how many records are to be written
* For TestTBL1 and TestTBL2
* Uses SQLBindParam () to bind the 4 paramaters
* For each record,
* prompts for data.
* calls SQLExecute () to execute the insert
* For TestTBL3 and TestTBL4
* Uses SQLDescribeParam () to get paramater attributes
* Uses SQLBindParameter () to bind the paramater with
* overall param size and, using SQL_LEN_DATA_AT_EXEC,
* the size of the chunks to be written each time when
* execute asks for more data.
* For each record,
* calls SQLExecute () to execute the insert
* Checks for SQL_NEED_DATA and calls SQLParamData ()
* to find out which of the text paramaters needs more
* data.
* While SQL_NEED_DATA returned,
* calls SQLPutData () to write data in chunks
* call SQLParamData () which will complete the
* current parameter and return a new param ID
* and SQL_NEED_DATA if any more paramaters need
* more data (e.g. the second Memo paramater).
*
* Use CreateTable to create TestTBL3 and/or TestTBL4
*/
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include "util.c"
#define MEMO1TEXTSIZE 12000
#define MEMO2TEXTSIZE 12000
#define PERSONID_LEN 2
#define LASTNAME_LEN 255
#define FIRSTNAME_LEN 255
#define ADDRESS_LEN 255
#define CITY_LEN 255
SQLLEN cPersonId;
SQLCHAR strFirstName[FIRSTNAME_LEN];
SQLCHAR strLastName[LASTNAME_LEN];
SQLCHAR strAddress[ADDRESS_LEN];
SQLCHAR strCity[CITY_LEN];
SQLLEN lenFirstName=0, lenLastName=0, lenAddress=0, lenCity=0;
int main () {
 SQLHENV henv = SQL_NULL_HENV; 	// Environment
 SQLHDBC hdbc = SQL_NULL_HDBC; 	// Connection handle
 SQLHSTMT hstmt = SQL_NULL_HSTMT; 	// Statement handle
 SQLRETURN retcode;
 // Tables
 // TestTBL1 has identity field 1 PersonID
 // TestTBL2 is same as TestTBL1 but without the identity field
 // TestTBL3 has one text field Memo1 in column 4
 // TestTBL4 is same as TestTBL3 plus another text field, Memo2 in columns 5
 	char sqlStatement[4][256]= {
 {"INSERT INTO TestTBL1 VALUES (?,?,?,?)"},
 {"INSERT INTO TestTBL2 VALUES (?,?,?,?)"},
 {"INSERT INTO TestTBL3 VALUES ('A N Other',55,'1958-12-25 00:00:00',?)"},
 {"INSERT INTO TestTBL4 VALUES ('A N Other',55,'1958-12-25 00:00:00',?,?)"}
 };
 int tableNo, numRecs;
 char confirm='N';
 char reply=' ';
 // SQLBindParameter variables (for TestTBL3 and TestTBL4).
 SQLLEN lenMemo1TextSize, lMemo1Bytes;
 SQLLEN lenMemo2TextSize, lMemo2Bytes;
 PTR pParamID;
 SQLSMALLINT NumParams, i, DataType, DecimalDigits, Nullable, paramNo;
 SQLULEN bytesRemaining;
 // SQLPutData text data for Memo1 (for TestTBL3 and TestTBL4).
 UCHAR Memo1Data[] =
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 "abcdefghijklmnopqrstuvwxyz";
 SDWORD lenMemo1Batch = (SDWORD)sizeof(Memo1Data) - 1;
 // SQLPutData text data for Memo1 (for TestTBL4).
 UCHAR Memo2Data[] =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 SDWORD lenMemo2Batch = (SDWORD)sizeof(Memo2Data) - 1;
 // used for each text parameter needing data
 SQLLEN lBytes;
 SDWORD lenBatch;
 UCHAR *Data;
 char strRecs[32];
 // get table for inserts ?
 reply=getInt ("Which Table"
 "\n0 (Quit)"
 "\n1 (TestTBL1 ID)"
 "\n2 (TestTBL2 NoID)"
 "\n3 (TestTBL3 Memo1)"
 "\n4 (TestTBL4 Memo1, Memo2)"
 "\n ?", &tableNo, confirm, 0);
 // or quit
 if (tableNo==0) goto exit;
 // 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);
 retcode=SQLDriverConnect(hdbc, NULL, "DSN=DATASOURCE;", SQL_NTS, NULL, 0,
 NULL, SQL_DRIVER_COMPLETE);
 CHECK_ERROR(retcode, "SQLDriverConnect(DATASOURCE)",
 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);
 printf ("Preparing : %s\n", &sqlStatement[tableNo-1][0]);
 retcode = SQLPrepare(hstmt, &sqlStatement[tableNo-1][0], SQL_NTS);
 CHECK_ERROR(retcode, "SQLPrepare(SQL_HANDLE_STMT)",
 hstmt, SQL_HANDLE_STMT);
 printf("SQLPrepare OK\n");
 retcode = SQLNumParams(hstmt, &NumParams);
 CHECK_ERROR(retcode, "SQLNumParams()", hstmt, SQL_HANDLE_STMT);
 printf("SQLNumParams(hstmt, &NumParams) OK\n");
 // Expecting DAE (Data at Execution) for :
 // if table 1 or 2 - 4 parameters - FirstName, LastName, Address, City
 // if table 3 - 1 parameter - for Memo1
 // if table 4 - 2 parameters - Memo1 and Memo2
 printf ("Num Params : %i\n", NumParams);
 if (NumParams) {
 switch (tableNo)
 {
 case 1: // TestTBL1 - should be asking for 4 params
 case 2: // TestTBL2 - should be asking for 4 params
 // Get Records to Add
 memset (strRecs, ' ', sizeof(strRecs));
 reply=getStr ("Number of Recs", strRecs, sizeof(strRecs), 'N');
 numRecs=atoi(strRecs);
 printf ("Writing %i records\n", numRecs);
 // Bind Parameters to all fields
 retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
 SQL_C_CHAR, SQL_CHAR, FIRSTNAME_LEN,
 0, strFirstName, FIRSTNAME_LEN,
 &lenFirstName);
 retcode = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT,
 SQL_C_CHAR, SQL_CHAR, LASTNAME_LEN,
 0, strLastName, LASTNAME_LEN,
 &lenLastName);
 retcode = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT,
 SQL_C_CHAR, SQL_CHAR, ADDRESS_LEN,
 0, strAddress, ADDRESS_LEN,
 &lenAddress);
 retcode = SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT,
 SQL_C_CHAR, SQL_CHAR, CITY_LEN,
 0, strCity, CITY_LEN, &lenCity);
 for (i=0;i<numRecs;i++) {
 // Setup data and lengths
 memset (strFirstName, ' ', FIRSTNAME_LEN);
 memset (strLastName, ' ', LASTNAME_LEN);
 memset (strAddress, ' ', ADDRESS_LEN);
 memset (strCity, ' ', CITY_LEN);
 // Get data from user
 getStr ("First Name", strFirstName, FIRSTNAME_LEN, 'N');
 getStr ("Last Name", strLastName, LASTNAME_LEN, 'N');
 getStr ("Address ", strAddress, ADDRESS_LEN, 'N');
 getStr ("City ", strCity, CITY_LEN, 'N');
 // Remove Nulls
 strFirstName[strlen(strFirstName)]=' ';
 strLastName[strlen(strLastName)]=' ';
 strAddress[strlen(strAddress)]=' ';
 strCity[strlen(strCity)]=' ';
 // Set sizes
 lenFirstName=sizeof(strFirstName);
 lenLastName=sizeof(strLastName);
 lenAddress=sizeof(strAddress);
 lenCity=sizeof(strCity);
 // Execute statement
 retcode = SQLExecute(hstmt);
 if (retcode == SQL_SUCCESS ||
 retcode == SQL_SUCCESS_WITH_INFO) {
 printf ("Status : ok\n");
 } else {
 printf ("Status : Error %i\n", retcode);
 }
 }
 break;
 case 3: // TestTBL3 - has text field Memo1
 case 4: // TestTBL4 - has text fields Memo1, Memo2
 // Get Records to Add
 memset (strRecs, ' ', sizeof(strRecs));
 reply=getStr ("Number of Recs", strRecs, sizeof(strRecs), 'N');
 numRecs=atoi(strRecs);
 for (i = 0; i < NumParams; i++) {
 // Describe the parameter.
 retcode = SQLDescribeParam(hstmt, i+1,
 &DataType,
 &bytesRemaining,
 &DecimalDigits,
 &Nullable);
 CHECK_ERROR(retcode, "SQLDescribeParam()",
 hstmt, SQL_HANDLE_STMT);
 printf("\nSQLDescribeParam() OK\n");
 printf("Data Type : %i, bytesRemaining : %i, DecimalDigits : %i, Nullable %i\n",
 (int)DataType, (int)bytesRemaining,
 (int)DecimalDigits, (int)Nullable);
 // Assume first param is for Memo1 text field
 if (i==0) {
 // Total number of bytes to write overall
 lMemo1Bytes=(SDWORD) MEMO1TEXTSIZE;
 // Chunk size to be written each time
 lenMemo1TextSize=SQL_LEN_DATA_AT_EXEC(lMemo1Bytes);
 printf ("Binding MEMO field 1 - ");
 printf ("Bytes Remaining : %i, ", (int)lMemo1Bytes);
 printf ("LenOrIndArray : %i\n", (int)lenMemo1TextSize);
 // For DATA_AT_EXEC parameter, whatever is passed in
 // parameter 8, is passed back in the second parameter
 // of SQLParamData () and used to find the field for
 // which more data is being requested.
 retcode = SQLBindParameter(
 hstmt, // Statment Handle
 i + 1, // Parameter Number
 SQL_PARAM_INPUT, // Type is INPUT
 SQL_C_CHAR, // C Type
 SQL_LONGVARCHAR, // SQL Type
 lMemo1Bytes, // Overall size
 0, // Decimal Digits
 Memo1Data, // Param value Pointer
 0, // Buffer Length
 &lenMemo1TextSize); // Chunk size
 CHECK_ERROR(retcode,
 "SQLBindParameter(3 SQL_PARAM_INPUT)",
 hstmt, SQL_HANDLE_STMT);
 }
 // Assume second param is for Memo2 text field
 if (i==1) {
 // Total number of bytes to write overall
 lMemo2Bytes=(SDWORD) MEMO2TEXTSIZE;
 // Chunk size to be written each time
 lenMemo2TextSize=SQL_LEN_DATA_AT_EXEC(lMemo2Bytes);
 printf ("Binding MEMO field 2 - ");
 printf ("Bytes Remaining : %i, ", (int)lMemo2Bytes);
 printf ("LenOrIndArray : %i\n", (int)lenMemo2TextSize);
 // For DATA_AT_EXEC parameter, whatever is passed in
 // parameter 8, is passed back in the second parameter
 // of SQLParamData () and used to find the field for
 // which more data is being requested.
 retcode = SQLBindParameter(
 hstmt, // Statment Handle
 i + 1, // Parameter Number
 SQL_PARAM_INPUT, // Type is INPUT
 SQL_C_CHAR, // C Type
 SQL_LONGVARCHAR, // SQL Type
 lMemo2Bytes, // Overall size
 0, // Decimal Digits
 Memo2Data, // Param value Pointer
 0, // Buffer Length
 &lenMemo2TextSize); // Chunk size
 CHECK_ERROR(retcode,
 "SQLBindParameter(4 SQL_PARAM_INPUT)",
 hstmt, SQL_HANDLE_STMT);
 }
 }
 // write 'numrecs' records to selected table
 for (i=0;i<numRecs;i++) {
 // Execute the command.
 printf ("\nCall SQLExecute\n");
 retcode = SQLExecute(hstmt);
 if ( (retcode != SQL_SUCCESS) &&
 (retcode != SQL_NEED_DATA) &&
 (retcode != SQL_SUCCESS_WITH_INFO) ) {
 CHECK_ERROR(retcode, "SQLExecute()",
 hstmt, SQL_HANDLE_STMT);
 }
 // we would expect SQLExecute to return SQL_NEED_DATA for
 // the DATA AT EXEC fields set up for either Memo1 or Memo2
 if (retcode==SQL_NEED_DATA) {
 // Find the parameter/column for which more data is need
 // SQLParamData returns (in pParamID) the value of
 // whatever was given in param 8 passed in the
 // SQLBindParameter call earlier, which in this example
 // is the address of the buffer for that parameter.
 printf ("First Call - SQLParamData\n");
 retcode = SQLParamData(hstmt, &pParamID);
 // parameter is Memo1
 if (pParamID==Memo1Data) {
 printf ("Need data for Memo1\n");
 lBytes=lMemo1Bytes;
 lenBatch=lenMemo1Batch;
 Data=Memo1Data;
 }
 // parameter is Memo2
 if (pParamID==Memo2Data) {
 printf ("Need data for Memo2\n");
 lBytes=lMemo2Bytes;
 lenBatch=lenMemo2Batch;
 Data=Memo2Data;
 }
 }
 // Loop round while asking for more data
 while (retcode == SQL_NEED_DATA) {
 printf ("Param ID : %p\n", pParamID);
 while (lBytes > lenBatch) {
 printf ("SQL_NEED_DATA Call SQLPutData : lBytes %i, lenBatch %i\n",
 (int)lBytes, (int)lenBatch);
 SQLPutData(hstmt, Data, lenBatch);
 lBytes -= lenBatch;
 }
 // Put final chunk.
 printf ("Final Call - SQLPutData : lMemo1Bytes %i\n",
 (int)lBytes);
 retcode = SQLPutData(hstmt, Data, lBytes);
 CHECK_ERROR(retcode, "SQLPutData()",
 hstmt, SQL_HANDLE_STMT);
 // Make final SQLParamData call for this paramater.
 printf ("Final Call - SQLParamData\n");
 retcode = SQLParamData(hstmt, &pParamID);
 if ( (retcode != SQL_SUCCESS) &&
 (retcode != SQL_SUCCESS_WITH_INFO) &&
 (retcode != SQL_NEED_DATA) ) {
 CHECK_ERROR(retcode, "SQLPutData()",
 hstmt, SQL_HANDLE_STMT);
 } else {
 // if the last call to SQLParamData returns
 // SQL_NEED_DATA again then another parameter
 // needs more data. (NOTE: the parameter
 // ordering is not necessarily guaranteed so
 // we check for which one more data is needed
 // for).
 if (retcode == SQL_NEED_DATA) {
 if (pParamID==Memo1Data) {
 printf ("Need data for Memo1\n");
 lBytes=lMemo1Bytes;
 lenBatch=lenMemo1Batch;
 Data=Memo1Data;
 }
 if (pParamID==Memo2Data) {
 printf ("Need data for Memo2\n");
 lBytes=lMemo2Bytes;
 lenBatch=lenMemo2Batch;
 Data=Memo2Data;
 }
 }
 }
 }
 }
 break;
 }
 } else {
 printf ("No Params\n");
 }
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

Download ODBC Drivers for

Oracle, SQL Server, Salesforce, MongoDB, Access, Derby, InterBase, DB2, & more.

Learn More
Share:

AltStyle によって変換されたページ (->オリジナル) /