Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Programmet binder kolumner genom att anropa SQLBindCol. Den här funktionen binder en kolumn i taget. Med det anger programmet följande:
Kolumnnumret. Kolumn 0 är bokmärkeskolumnen. den här kolumnen ingår inte i vissa resultatuppsättningar. Alla andra kolumner numreras från och med talet 1. Det är ett fel att binda en kolumn med högre nummer än det finns kolumner i resultatuppsättningen. Det går inte att identifiera det här felet förrän resultatuppsättningen har skapats, så den returneras av SQLFetch, inte SQLBindCol.
C-datatypen, adressen och bytelängden för variabeln som är bunden till kolumnen. Det är ett fel att ange en C-datatyp som SQL-datatypen för kolumnen inte kan konverteras till. Det här felet kanske inte identifieras förrän resultatuppsättningen har skapats, så den returneras av SQLFetch, inte SQLBindCol. En lista över konverteringar som stöds finns i Konvertera data från SQL till C-datatyper i bilaga D: Datatyper. Information om bytelängden finns i Databuffertlängd.
Adressen till en längd-/indikatorbuffert. Bufferten för längd/indikator är valfri. Den används för att returnera bytelängden för binära data eller teckendata eller returnera SQL_NULL_DATA om data är NULL. Mer information finns i Använda längd/indikatorvärden.
När SQLBindCol anropas associerar drivrutinen den här informationen med -instruktionen. När varje rad med data hämtas använder den informationen för att placera data för varje kolumn i de bundna programvariablerna.
Följande kod binder till exempel variabler till kolumnerna SalesPerson och CustID. Data för kolumnerna returneras i SalesPerson och CustID. Eftersom SalesPerson är en teckenbuffert anger programmet dess bytelängd (11) så att drivrutinen kan avgöra om data ska trunkeras. Bytelängden för den returnerade rubriken, eller om den är NULL, returneras i SalesPersonLenOrInd.
Eftersom CustID är en heltalsvariabel och har fast längd behöver du inte ange bytelängden. -drivrutinen förutsätter att den är sizeof(SQLUINTEGER). Bytelängden för returnerade kund-ID-data, eller om de är NULL, returneras i CustIDInd. Observera att programmet bara är intresserat av om lönen är NULL, eftersom bytelängden alltid är sizeof(SQLUINTEGER).
SQLCHAR SalesPerson[11];
SQLUINTEGER CustID;
SQLINTEGER SalesPersonLenOrInd, CustIDInd;
SQLRETURN rc;
SQLHSTMT hstmt;
// Bind SalesPerson to the SalesPerson column and CustID to the
// CustID column.
SQLBindCol(hstmt, 1, SQL_C_CHAR, SalesPerson, sizeof(SalesPerson),
&SalesPersonLenOrInd);
SQLBindCol(hstmt, 2, SQL_C_ULONG, &CustID, 0, &CustIDInd);
// Execute a statement to get the sales person/customer of all orders.
SQLExecDirect(hstmt, "SELECT SalesPerson, CustID FROM Orders ORDER BY SalesPerson",
SQL_NTS);
// Fetch and print the data. Print "NULL" if the data is NULL. Code to
// check if rc equals SQL_ERROR or SQL_SUCCESS_WITH_INFO not shown.
while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA) {
if (SalesPersonLenOrInd == SQL_NULL_DATA)
printf("NULL ");
else
printf("%10s ", SalesPerson);
if (CustIDInd == SQL_NULL_DATA)
printf("NULL\n");
else
printf("%d\n", CustID);
}
// Close the cursor.
SQLCloseCursor(hstmt);
Följande kod kör en SELECT-instruktion som angetts av användaren och skriver ut varje rad med data i resultatuppsättningen. Eftersom programmet inte kan förutsäga formen på resultatuppsättningen som skapats av SELECT-instruktionen kan det inte binda hårdkodade variabler till resultatuppsättningen som i föregående exempel. I stället allokerar programmet en buffert som innehåller data och en längd/indikatorbuffert för varje kolumn i den raden. För varje kolumn beräknar den förskjutningen till början av minnet för kolumnen och justerar den här förskjutningen så att data- och längd-/indikatorbuffertarna för kolumnen börjar vid justeringsgränser. Det binder sedan minnet från och med förskjutningen till kolumnen. Från drivrutinens synvinkel är adressen för det här minnet oskiljaktig från adressen för en variabel som är bunden i föregående exempel. Mer information om justering finns i Justering.
// This application allocates a buffer at run time. For each column, this
// buffer contains memory for the column's data and length/indicator.
// For example:
// column 1 column 2 column 3 column 4
// <------------><---------------><-----><------------>
// db1 li1 db2 li2 db3 li3 db4 li4
// | | | | | | | |
// _____V_____V________V_______V___V___V______V_____V_
// |__________|__|_____________|__|___|__|__________|__|
//
// dbn = data buffer for column n
// lin = length/indicator buffer for column n
// Define a macro to increase the size of a buffer so that it is a
// multiple of the alignment size. Thus, if a buffer starts on an
// alignment boundary, it will end just before the next alignment
// boundary. In this example, an alignment size of 4 is used because
// this is the size of the largest data type used in the application's
// buffer--the size of an SDWORD and of the largest default C data type
// are both 4. If a larger data type (such as _int64) was used, it would
// be necessary to align for that size.
#define ALIGNSIZE 4
#define ALIGNBUF(Length) Length % ALIGNSIZE ? \
Length + ALIGNSIZE - (Length % ALIGNSIZE) : Length
SQLCHAR SelectStmt[100];
SQLSMALLINT NumCols, *CTypeArray, i;
SQLINTEGER * ColLenArray, *OffsetArray, SQLType, *DataPtr;
SQLRETURN rc;
SQLHSTMT hstmt;
// Get a SELECT statement from the user and execute it.
GetSelectStmt(SelectStmt, 100);
SQLExecDirect(hstmt, SelectStmt, SQL_NTS);
// Determine the number of result set columns. Allocate arrays to hold
// the C type, byte length, and buffer offset to the data.
SQLNumResultCols(hstmt, &NumCols);
CTypeArray = (SQLSMALLINT *) malloc(NumCols * sizeof(SQLSMALLINT));
ColLenArray = (SQLINTEGER *) malloc(NumCols * sizeof(SQLINTEGER));
OffsetArray = (SQLINTEGER *) malloc(NumCols * sizeof(SQLINTEGER));
OffsetArray[0] = 0;
for (i = 0; i < NumCols; i++) {
// Determine the column's SQL type. GetDefaultCType contains a switch
// statement that returns the default C type for each SQL type.
SQLColAttribute(hstmt, ((SQLUSMALLINT) i) + 1, SQL_DESC_TYPE, NULL, 0, NULL, (SQLPOINTER) &SQLType);
CTypeArray[i] = GetDefaultCType(SQLType);
// Determine the column's byte length. Calculate the offset in the
// buffer to the data as the offset to the previous column, plus the
// byte length of the previous column, plus the byte length of the
// previous column's length/indicator buffer. Note that the byte
// length of the column and the length/indicator buffer are increased
// so that, assuming they start on an alignment boundary, they will
// end on the byte before the next alignment boundary. Although this
// might leave some holes in the buffer, it is a relatively
// inexpensive way to guarantee alignment.
SQLColAttribute(hstmt, ((SQLUSMALLINT) i)+1, SQL_DESC_OCTET_LENGTH, NULL, 0, NULL, &ColLenArray[i]);
ColLenArray[i] = ALIGNBUF(ColLenArray[i]);
if (i)
OffsetArray[i] = OffsetArray[i-1]+ColLenArray[i-1]+ALIGNBUF(sizeof(SQLINTEGER));
}
// Allocate the data buffer. The size of the buffer is equal to the
// offset to the data buffer for the final column, plus the byte length
// of the data buffer and length/indicator buffer for the last column.
void *DataPtr = malloc(OffsetArray[NumCols - 1] +
ColLenArray[NumCols - 1] + ALIGNBUF(sizeof(SQLINTEGER)));
// For each column, bind the address in the buffer at the start of the
// memory allocated for that column's data and the address at the start
// of the memory allocated for that column's length/indicator buffer.
for (i = 0; i < NumCols; i++)
SQLBindCol(hstmt,
((SQLUSMALLINT) i) + 1,
CTypeArray[i],
(SQLPOINTER)((SQLCHAR *)DataPtr + OffsetArray[i]),
ColLenArray[i],
(SQLINTEGER *)((SQLCHAR *)DataPtr + OffsetArray[i] + ColLenArray[i]));
// Retrieve and print each row. PrintData accepts a pointer to the data,
// its C type, and its byte length/indicator. It contains a switch
// statement that casts and prints the data according to its type. Code
// to check if rc equals SQL_ERROR or SQL_SUCCESS_WITH_INFO not shown.
while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA) {
for (i = 0; i < NumCols; i++) {
PrintData((SQLCHAR *)DataPtr[OffsetArray[i]], CTypeArray[i],
(SQLINTEGER *)((SQLCHAR *)DataPtr[OffsetArray[i] + ColLenArray[i]]));
}
}
// Close the cursor.
SQLCloseCursor(hstmt);