Zeilenbezogenes Binden

Bei Verwendung der zeilenweisen Bindung definiert eine Anwendung eine Struktur, die ein oder zwei enthält, oder in einigen Fällen drei Elemente für jede Spalte, für die Daten zurückgegeben werden sollen. Das erste Element enthält den Datenwert, und das zweite Element enthält den Längen-/Indikatorpuffer. Indikatoren und Längenwerte können in separaten Puffern gespeichert werden, indem die Felder SQL_DESC_INDICATOR_PTR und SQL_DESC_OCTET_LENGTH_PTR Deskriptor auf unterschiedliche Werte festgelegt werden; Wenn dies der Fall ist, enthält die Struktur ein drittes Element. Die Anwendung weist dann ein Array dieser Strukturen zu, das so viele Elemente enthält, wie zeilen im Rowset vorhanden sind.

Die Anwendung deklariert die Größe der Struktur an den Treiber mit dem attribut SQL_ATTR_ROW_BIND_TYPE-Anweisung und bindet die Adresse jedes Elements im ersten Element des Arrays. Der Treiber kann somit die Adresse der Daten für eine bestimmte Zeile und Spalte berechnen als

Address = Bound Address + ((Row Number - 1) * Structure Size)  

wobei Zeilen von 1 bis zur Größe des Rowsets nummeriert werden. (Eine wird von der Zeilennummer subtrahiert, da die Arrayindizierung in C nullbasiert ist.) Die folgende Abbildung zeigt, wie zeilenweise Bindung funktioniert. Im Allgemeinen sind nur Spalten, die gebunden werden, in der Struktur enthalten. Die Struktur kann Felder enthalten, die nicht mit Resultsetspalten verknüpft sind. Die Spalten können in beliebiger Reihenfolge in der Struktur platziert werden, werden jedoch in sequenzieller Reihenfolge zur Übersichtlichkeit angezeigt.

Shows row-wise binding

Der folgende Code erstellt z. B. eine Struktur mit Elementen, in denen Daten für die Spalten "OrderID", "SalesPerson" und "Status" zurückgegeben werden sollen, sowie Länge/Indikatoren für die Spalten "SalesPerson" und "Status". Sie weist 10 dieser Strukturen zu und bindet sie an die Spalten "OrderID", "SalesPerson" und "Status".

#define ROW_ARRAY_SIZE 10  
  
// Define the ORDERINFO struct and allocate an array of 10 structs.  
typedef struct {  
   SQLUINTEGER   OrderID;  
   SQLINTEGER    OrderIDInd;  
   SQLCHAR       SalesPerson[11];  
   SQLINTEGER    SalesPersonLenOrInd;  
   SQLCHAR       Status[7];  
   SQLINTEGER    StatusLenOrInd;  
} ORDERINFO;  
ORDERINFO OrderInfoArray[ROW_ARRAY_SIZE];  
  
SQLULEN    NumRowsFetched;  
SQLUSMALLINT   RowStatusArray[ROW_ARRAY_SIZE], i;  
SQLRETURN      rc;  
SQLHSTMT       hstmt;  
  
// Specify the size of the structure with the SQL_ATTR_ROW_BIND_TYPE  
// statement attribute. This also declares that row-wise binding will  
// be used. Declare the rowset size with the SQL_ATTR_ROW_ARRAY_SIZE  
// statement attribute. Set the SQL_ATTR_ROW_STATUS_PTR statement  
// attribute to point to the row status array. Set the  
// SQL_ATTR_ROWS_FETCHED_PTR statement attribute to point to  
// NumRowsFetched.  
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, sizeof(ORDERINFO), 0);  
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, ROW_ARRAY_SIZE, 0);  
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);  
SQLSetStmtAttr(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, &NumRowsFetched, 0);  
  
// Bind elements of the first structure in the array to the OrderID,  
// SalesPerson, and Status columns.  
SQLBindCol(hstmt, 1, SQL_C_ULONG, &OrderInfoArray[0].OrderID, 0, &OrderInfoArray[0].OrderIDInd);  
SQLBindCol(hstmt, 2, SQL_C_CHAR, OrderInfoArray[0].SalesPerson,  
            sizeof(OrderInfoArray[0].SalesPerson),  
            &OrderInfoArray[0].SalesPersonLenOrInd);  
SQLBindCol(hstmt, 3, SQL_C_CHAR, OrderInfoArray[0].Status,  
            sizeof(OrderInfoArray[0].Status), &OrderInfoArray[0].StatusLenOrInd);  
  
// Execute a statement to retrieve rows from the Orders table.  
SQLExecDirect(hstmt, "SELECT OrderID, SalesPerson, Status FROM Orders", SQL_NTS);  
  
// Fetch up to the rowset size number of rows at a time. Print the actual  
// number of rows fetched; this number is returned in NumRowsFetched.  
// Check the row status array to print only those rows successfully  
// fetched. Code to check if rc equals SQL_SUCCESS_WITH_INFO or  
// SQL_ERRORnot shown.  
while ((rc = SQLFetchScroll(hstmt,SQL_FETCH_NEXT,0)) != SQL_NO_DATA) {  
   for (i = 0; i < NumRowsFetched; i++) {  
      if (RowStatusArray[i] == SQL_ROW_SUCCESS|| RowStatusArray[i] ==   
         SQL_ROW_SUCCESS_WITH_INFO) {  
         if (OrderInfoArray[i].OrderIDInd == SQL_NULL_DATA)  
            printf(" NULL      ");  
         else  
            printf("%d\t", OrderInfoArray[i].OrderID);  
         if (OrderInfoArray[i].SalesPersonLenOrInd == SQL_NULL_DATA)  
            printf(" NULL      ");  
         else  
            printf("%s\t", OrderInfoArray[i].SalesPerson);  
         if (OrderInfoArray[i].StatusLenOrInd == SQL_NULL_DATA)  
            printf(" NULL\n");  
         else  
            printf("%s\n", OrderInfoArray[i].Status);  
      }  
   }  
}  
  
// Close the cursor.  
SQLCloseCursor(hstmt);