Megosztás:


Az SQLBindCol használata

Az alkalmazás az SQLBindCol meghívásával köti össze az oszlopokat. Ez a függvény egyszerre egy oszlopot köt össze. Ezzel az alkalmazás a következőket adja meg:

  • Az oszlop száma. A 0. oszlop a könyvjelző oszlop; ez az oszlop nem szerepel egyes eredményhalmazokban. Az összes többi oszlop számozása az 1-es számmal kezdődik. Hiba egy nagyobb számmal rendelkező oszlop hozzárendelése, mint amennyi oszlop van az eredményhalmazban; ez a hiba csak akkor észlelhető, ha az eredményhalmaz létrejött, ezért nem az SQLBindCol, hanem az SQLFetch adja vissza.

  • Az oszlophoz kötött változó C adattípusa, címe és bájthossza. Hiba olyan C adattípust megadni, amelybe az oszlop SQL-adattípusa nem konvertálható; Előfordulhat, hogy a hiba csak az eredményhalmaz létrehozása után észlelhető, ezért az SQLFetch nem az SQLBindCol, hanem az SQLFetch adja vissza. A támogatott konverziók listájáért lásd: Adatok konvertálása SQL-ből C adattípusokká a D függelékben: Adattípusok. A bájthosszról további információt az Adatpuffer hossza című témakörben talál.

  • A hossz-/jelzőpuffer címe. A hossz-/mutatópuffer megadása nem kötelező. A bináris vagy karakteradatok bájthosszának visszaadására vagy SQL_NULL_DATA visszaadására szolgál, ha az adatok NULL értékűek. További információ: Hossz/Mutatóértékek használata.

Az SQLBindCol meghívásakor az illesztőprogram társítja ezeket az információkat az utasítással. Az egyes adatsorok beolvasásakor az információt arra használja, hogy az egyes oszlopok adatait a kötött alkalmazásváltozókban elhelyezze.

Az alábbi kód például a SalesPerson és a CustID oszlophoz köti a változókat. Az oszlopok adatai a SalesPerson és a CustID formátumban lesznek visszaadva. Mivel a SalesPerson egy karakterpuffer, az alkalmazás megadja a bájthosszát (11), hogy az illesztőprogram meg tudja állapítani, hogy csonkítani szeretné-e az adatokat. A visszaadott cím bájthossza vagy null értéke a SalesPersonLenOrInd függvényben lesz visszaadva.

Mivel a CustID egy egész szám változó, és rögzített hosszúságú, nincs szükség a bájthossz megadására; az illesztőprogram feltételezi, hogy sizeof(SQLUINTEGER). A visszaadott ügyfél-azonosító adatainak bájthosszát vagy nullértékét a CustIDInd függvény adja vissza. Vegye figyelembe, hogy az alkalmazást csak az érdekli, hogy a fizetés NULL-e, mert a bájthossz mindig 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);  

Az alábbi kód végrehajtja a felhasználó által megadott SELECT utasítást, és az eredményhalmaz minden adatsorát kinyomtatja. Mivel az alkalmazás nem tudja előrejelezni a SELECT utasítás által létrehozott eredményhalmaz alakját, nem köthet kemény kódú változókat az eredményhalmazhoz az előző példában leírtak szerint. Ehelyett az alkalmazás lefoglal egy puffert, amely tartalmazza az adatokat, és egy hossz/mutató puffert az adott sor minden oszlopához. Minden oszlop esetében kiszámítja az oszlop memória elejének eltolását, és úgy módosítja ezt az eltolást, hogy az oszlop adat- és hossz-/mutatópufferei igazítási határvonalakon kezdődjenek. Ezután az eltolástól kezdődő memóriát az oszlophoz köti. Az illesztőprogram szempontjából ennek a memórianek a címe megkülönböztethetetlen az előző példában kötött változó címétől. Az igazításról további információt az Igazítás című témakörben talál.

// 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);