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 : TVPInsertRecs.c
*
* DESCRIPTION :
* Demonstrates a simple example of using a Table-Valued Parameter
* (TVP) to populate a table using a stored procedure with just one
* parameter. TVPs were introduced in SQL SERVER 2008. A TVP is a
* data type that can be used to hold records in a 'table' like
* manner but are held within a variable inside a program. The
* whole of the 'table' like parameter can then be passed as a
* single parameter to a stored procedure for processing. For
* example, TVPs can be usefully applied when performing bulk data
* operations where a whole set of rows can be passed as a single
* parameter to a stored procedure for subsequent inserting into
* a database table.
*
* ODBC USAGE :
*
* The TVP used here represents a table type with 4 columns:
* FirstName, LastName, Address and City.
*
* Prompts user for number of records to create
*
* Sets up the test by dropping and re-creating:-
* 1. Database Table (TestTVPTable1) - into which rows
* are written from rows in a TVP.
* 2. Stored Procedure (InsertFromTVP) - to select records
* from the TVP and insert them into TestTVPTable1.
* 3. TVP Table Variable (PersonTVP) - Table variable to
* hold records and passed as a single parameter to
* InsertFromTVP().
*
* Bind Paramaters:
* Binds parameter 1 as a TVP
*
* Bind TVP Parameters:
* Sets focus on parameter 1
* Bind arrays to each of the 4 TVP columns and lengths. i.e.
* for FirstName, LastName, Address and City
* Clears focus by setting focus to zero
*
* Load data into the TVP bound arrays:
* For the number of records requested
* prompts user for each of the four columns per row
* and save each set in the next row of the TVP bound buffers
* Execute the stores procedure to insert the records stored in the
* TVP bound array buffers. Note the stored procedure only takes
* one parameter, the TVP, but upto as many as MAX_ARRAY_SIZE records
* are written to the table.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <sqlncli.h>
#include <string.h>
#include "util.c"
#define LASTNAME_LEN 255
#define FIRSTNAME_LEN 255
#define ADDRESS_LEN 255
#define CITY_LEN 255
#define MAX_ARRAY_SIZE 20
//
// SetupTVPTest is used to create and/or drop the stored procedure,
// TVP table type and DB Table used in the test.
//
SQLRETURN SetupTVPTest (SQLHDBC hdbc, char createEm, char dropEm) {
 SQLHSTMT hstmt = SQL_NULL_HSTMT; 	// Statement handle
 SQLRETURN retcode = SQL_SUCCESS;	// Return status
 // Drop statements
 // Stored Procedure
 SQLCHAR strDropTVPProc [] =
 "IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = "
 "object_id(N'dbo.InsertFromTVP') AND OBJECTPROPERTY"
 "(id, N'IsProcedure') = 1) DROP PROCEDURE dbo.InsertFromTVP";
 // TVP Table Type
 SQLCHAR strDropTVPType[] =
 "IF EXISTS (SELECT * FROM sys.types WHERE "
 "is_table_type = 1 AND name = 'PersonTVP') "
 "DROP TYPE dbo.PersonTVP";
 // TVP Table (the physical one in the DB)
 SQLCHAR strDropTVPTable [] =
 "IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = "
 "object_id(N'dbo.TestTVPTable1') AND OBJECTPROPERTY(id, N'IsUserTable')"
 " = 1) DROP TABLE dbo.TestTVPTable1";
 // Create the physical database table
 SQLCHAR strCreateTVPTable [] =
 "CREATE TABLE TestTVPTable1 ("
 "PersonID int NOT NULL IDENTITY(1,1),"
 "FirstName varchar(255),"
 "LastName varchar(255),"
 "Address varchar(255),"
 "City varchar(255)"
 ")";
 // Create the in-memory Table-Value Parameter Table
 SQLCHAR strCreateTVPType [] =
 "CREATE TYPE PersonTVP AS TABLE ( "
 "vFirstName varchar(255),"
 "vLastName varchar(255),"
 "vAddress varchar(255),"
 "vCity varchar(255)"
 ")";
 // Create the stored procedure which takes one parameter,
 // the persons Table-Value Parameter Table.
 // NOTE: Table-value Params Must be read only.
 SQLCHAR strCreateTVPProc [] =
 "CREATE PROCEDURE InsertFromTVP (@Persons PersonTVP READONLY) "
 "AS "
 "INSERT INTO TestTVPTable1 (FirstName, LastName, Address, City) "
 "SELECT vFirstName, vLastName, vAddress, vCity FROM @Persons";
 // Allocate a statement handle
 retcode=SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
 CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_STMT)",
 hstmt, SQL_HANDLE_STMT);
 if (dropEm=='Y') {
 	// Execute Drop Procedure
 	retcode = SQLExecDirect (hstmt, strDropTVPProc, SQL_NTS);
 CHECK_ERROR(retcode, "SQLExecDirect(DROPPROC)",
 hstmt, SQL_HANDLE_STMT);
 	// Execute Drop Type
 	retcode = SQLExecDirect (hstmt, strDropTVPType, SQL_NTS);
 CHECK_ERROR(retcode, "SQLExecDirect(DROPTYPE)",
 hstmt, SQL_HANDLE_STMT);
 	// Execute DROP Table
 	retcode = SQLExecDirect (hstmt, strDropTVPTable, SQL_NTS);
 CHECK_ERROR(retcode, "SQLExecDirect(DROPTABLE)",
 hstmt, SQL_HANDLE_STMT);
 }
 if (createEm=='Y')
 // Execute Create Table
 retcode = SQLExecDirect (hstmt, strCreateTVPTable, SQL_NTS);
 CHECK_ERROR(retcode, "SQLExecDirect(CREATETABLE)",
 hstmt, SQL_HANDLE_STMT);
 // Execute Create Type
 retcode = SQLExecDirect (hstmt, strCreateTVPType, SQL_NTS);
 CHECK_ERROR(retcode, "SQLExecDirect(CREATETYPE)",
 hstmt, SQL_HANDLE_STMT);
 // Execute Create Procedure
 retcode = SQLExecDirect (hstmt, strCreateTVPProc, SQL_NTS);
 CHECK_ERROR(retcode, "SQLExecDirect(CREATEPROC)",
 hstmt, SQL_HANDLE_STMT);
exit:
 // Free statement handle
 if (hstmt != SQL_NULL_HSTMT)
 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
 return retcode;
}
//
// Arrays of column values
//
SQLCHAR strFirstName [MAX_ARRAY_SIZE][FIRSTNAME_LEN];
SQLCHAR strLastName[MAX_ARRAY_SIZE][LASTNAME_LEN];
SQLCHAR strAddress[MAX_ARRAY_SIZE][ADDRESS_LEN];
SQLCHAR strCity[MAX_ARRAY_SIZE][CITY_LEN];
//
// Arrays of column values lengths
//
SQLLEN lFirstName[MAX_ARRAY_SIZE];
SQLLEN lLastName[MAX_ARRAY_SIZE];
SQLLEN lAddress[MAX_ARRAY_SIZE];
SQLLEN lCity[MAX_ARRAY_SIZE];
int main () {
 SQLHENV henv = SQL_NULL_HENV; 	// Environment
 SQLHDBC hdbc = SQL_NULL_HDBC; 	// Connection handle
 SQLHSTMT hstmt = SQL_NULL_HSTMT; 	// Statement handle
 SQLRETURN retcode;			// Return status
 int i, numRows=1;
 // The name of the TVP table data type
 SQLCHAR *TVPTableName = (SQLCHAR *) "PersonTVP";
 SQLLEN lTVPRowsUsed;
 // Get Number of records to insert
 getInt ("Number of Recs", &numRows, 'N', 0);
 if (numRows==0) goto exit;
 if (numRows>MAX_ARRAY_SIZE) numRows=MAX_ARRAY_SIZE;
 // Allocate environment
 retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
 CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_ENV)",
 henv, SQL_HANDLE_ENV);
 // Set ODBC Verion
 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 Connection
 retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
 CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_DBC)",
 henv, SQL_HANDLE_DBC);
 // Set Login Timeout
 retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
 CHECK_ERROR(retcode, "SQLSetConnectAttr(SQL_LOGIN_TIMEOUT)",
 hdbc, SQL_HANDLE_DBC);
 // Connect to DSN
 retcode = SQLConnect(hdbc, (SQLCHAR*) "SQLSRV2014", SQL_NTS,
 (SQLCHAR*) NULL, 0, NULL, 0);
 CHECK_ERROR(retcode, "SQLConnect(DSN: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);
 // Setup stored procedure, Table-Value Parameter data type and database
 // Table.
 // Second parameter indicates whether the above are to be created
 // Third parameter indicates whether the above are to be dropped
 retcode = SetupTVPTest (hdbc, 'Y', 'Y');
 CHECK_ERROR(retcode, "SetupTVPTest()", hdbc, SQL_HANDLE_DBC);
 //
 // 1st step is bind all parameters in normal way.
 // Here we have just one parameter, a Table-Valued Parameter (TVP)
 // which requires some specific parameters.
 //
 retcode = SQLBindParameter(
 hstmt, // Statement handle
 1, // Parameter Number
 SQL_PARAM_INPUT, // Input/Output Type (always INPUT for TVP)
 SQL_C_DEFAULT, // C - Type (always this for a TVP)
 SQL_SS_TABLE, // SQL Type (always this for a TVP)
 MAX_ARRAY_SIZE, // For a TVP this is max rows we will use
 0, // For a TVP this is always 0
 TVPTableName, // For a TVP this is the type name of the
 // TVP, and also a token returned by
 // SQLParamData.
 SQL_NTS, // For a TVP this is the length of the type
 // name or SQL_NTS.
 &lTVPRowsUsed); // For a TVP this is the number of rows
 // actually available.
 //
 // Now we need to bind a separate set of parameters for each TVP.
 // To do we set the focus on each TVP in turn, bind data to it in the same
 // way as for rows in a table.
 //
 // First set focus on param 1.
 retcode = SQLSetStmtAttr(hstmt, SQL_SOPT_SS_PARAM_FOCUS,
 (SQLPOINTER) 1, SQL_IS_INTEGER);
 // Col 1 - Bind start of FirstName array
 retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
 SQL_C_CHAR, SQL_CHAR,
 FIRSTNAME_LEN, 0, &strFirstName[0],
 FIRSTNAME_LEN, &lFirstName[0]);
 // Col 2 - Bind start of LastName array
 retcode = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT,
 SQL_C_CHAR, SQL_CHAR,
 LASTNAME_LEN, 0, &strLastName[0],
 LASTNAME_LEN, &lLastName[0]);
 // Col 3 - Bind start of Address array
 retcode = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT,
 SQL_C_CHAR, SQL_CHAR, ADDRESS_LEN,
 0, &strAddress[0],
 ADDRESS_LEN, &lAddress[0]);
 // Col 4 - Bind start of City array
 retcode = SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT,
 SQL_C_CHAR, SQL_CHAR, CITY_LEN,
 0, &strCity[0], CITY_LEN, &lCity[0]);
 //
 // If there were further TVPs we would set the focus to the next one,
 // bind buffers to that, and so on on until all TVPs have bound buffers.
 // As we have no more, reset param focus to zero.
 //
 retcode = SQLSetStmtAttr(hstmt, SQL_SOPT_SS_PARAM_FOCUS,
 (SQLPOINTER) 0, SQL_IS_INTEGER);
 //
 // The data for each row of the TVP is represented by the nth element of
 // the arrays bound for columns FirstName, LastName, Address and City,
 // held in strFirtstName[n], strLastName[n], strAddress[n], and strCity[n]
 // Prompt for data, filling columns and rows until numRows reached.
 //
 for (i=0;i<numRows;i++) {
 // Clear Buffers
 memset (strFirstName[i], ' ', FIRSTNAME_LEN);
 memset (strLastName[i], ' ', LASTNAME_LEN);
 memset (strAddress[i], ' ', ADDRESS_LEN);
 memset (strCity[i], ' ', CITY_LEN);
 // Get data from user
 printf ("\nRecord %i, out of %i\n\n", i+1, numRows);
 getStr ("First Name", strFirstName[i], FIRSTNAME_LEN, 'N');
 getStr ("Last Name", strLastName[i], LASTNAME_LEN, 'N');
 getStr ("Address ", strAddress[i], ADDRESS_LEN, 'N');
 getStr ("City ", strCity[i], CITY_LEN, 'N');
 // Set lengths
 lFirstName[i]=strlen(strFirstName[i]);
 lLastName[i]=strlen(strLastName[i]);
 lAddress[i]=strlen(strAddress[i]);
 lCity[i]=strlen(strCity[i]);
 }
 //
 // We now have arrays holding FirstNames, Lastnames, Addresses and Citys,
 // and corresponding lengths for each.
 //
 // Set the StrLen_or_IndPtr value to the actual number of rows to write
 // (i.e. in the buffers) and execute the stored procedure. Although just
 // one parameter is passed, because it is a TVP, several rows are actually
 // written to the table.
 //
 lTVPRowsUsed=numRows;
 retcode = SQLExecDirect(hstmt, "{CALL InsertFromTVP(?)}", SQL_NTS);
 CHECK_ERROR(retcode, "SQLExecDirect(InsertFromTVP)",
 hstmt, SQL_HANDLE_STMT);
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 によって変換されたページ (->オリジナル) /