Aktualisieren von Zeilen im Rowset mit SQLSetPos

Mit dem Aktualisierungsvorgang von SQLSetPos wird die Datenquelle eine oder mehrere ausgewählte Zeilen einer Tabelle aktualisiert, wobei Daten in den Anwendungspuffern für jede gebundene Spalte verwendet werden (es sei denn, der Wert im Längen-/Indikatorpuffer ist SQL_COLUMN_IGNORE). Spalten, die nicht gebunden sind, werden nicht aktualisiert.

Zum Aktualisieren von Zeilen mit SQLSetPos führt die Anwendung die folgenden Aktionen aus:

  1. Platziert die neuen Datenwerte in den Rowsetpuffern. Informationen zum Senden langer Daten mit SQLSetPos finden Sie unter Long Data and SQLSetPos und SQLBulkOperations.

  2. Legt den Wert im Längen-/Indikatorpuffer jeder Spalte bei Bedarf fest. Dies ist die Bytelänge der Daten oder SQL_NTS für Spalten, die an Zeichenfolgenpuffer gebunden sind, die Bytelänge der Daten für Spalten, die an binäre Puffer gebunden sind, und SQL_NULL_DATA, damit alle Spalten auf NULL festgelegt werden.

  3. Legt den Wert im Längen-/Indikatorpuffer dieser Spalten fest, die nicht auf SQL_COLUMN_IGNORE aktualisiert werden sollen. Obwohl die Anwendung diesen Schritt überspringen und vorhandene Daten erneut senden kann, ist dies ineffizient und riskiert das Senden von Werten an die Datenquelle, die beim Lesen abgeschnitten wurden.

  4. Ruft SQLSetPos mit operation set to SQL_UPDATE and RowNumber set to the number of the row to update. Wenn RowNumber 0 ist, werden alle Zeilen im Rowset aktualisiert.

Nachdem SQLSetPos zurückgegeben wurde, wird die aktuelle Zeile auf die aktualisierte Zeile festgelegt.

Beim Aktualisieren aller Zeilen des Rowsets (RowNumber ist gleich 0) kann eine Anwendung die Aktualisierung bestimmter Zeilen deaktivieren, indem sie die entsprechenden Elemente des Zeilenvorgangsarrays (verweist auf das attribut der SQL_ATTR_ROW_OPERATION_PTR-Anweisung) auf SQL_ROW_IGNORE festlegen. Das Zeilenvorgangsarray entspricht der Größe und Anzahl der Elemente dem Zeilenstatusarray (verweist auf das attribut SQL_ATTR_ROW_STATUS_PTR-Anweisung). Um nur die Zeilen im Resultset zu aktualisieren, die erfolgreich abgerufen und nicht aus dem Rowset gelöscht wurden, verwendet die Anwendung das Zeilenstatusarray aus der Funktion, die das Rowset als Zeilenvorgangsarray in SQLSetPos abgerufen hat.

Für jede Zeile, die als Aktualisierung an die Datenquelle gesendet wird, sollten die Anwendungspuffer über gültige Zeilendaten verfügen. Wenn die Anwendungspuffer durch Abrufen und Wenn ein Zeilenstatusarray Standard tained wurde, sollten die Werte an jeder dieser Zeilenpositionen nicht SQL_ROW_DELETED, SQL_ROW_ERROR oder SQL_ROW_NOROW sein.

Mit dem folgenden Code kann ein Benutzer beispielsweise durch die Tabelle "Customers" scrollen und neue Zeilen aktualisieren, löschen oder hinzufügen. Sie platziert die neuen Daten in den Rowsetpuffern, bevor SQLSetPos aufgerufen wird, um neue Zeilen zu aktualisieren oder hinzuzufügen. Am Ende der Rowsetpuffer wird eine zusätzliche Zeile zugewiesen, um neue Zeilen zu enthalten; Dadurch wird verhindert, dass vorhandene Daten überschrieben werden, wenn Daten für eine neue Zeile in den Puffern platziert werden.

#define UPDATE_ROW   100  
#define DELETE_ROW   101  
#define ADD_ROW      102  
  
SQLUINTEGER    CustIDArray[11];  
SQLCHAR        NameArray[11][51], AddressArray[11][51],   
               PhoneArray[11][11];  
SQLINTEGER     CustIDIndArray[11], NameLenOrIndArray[11],   
               AddressLenOrIndArray[11],  
               PhoneLenOrIndArray[11];  
SQLUSMALLINT   RowStatusArray[10], Action, RowNum;  
SQLRETURN      rc;  
SQLHSTMT       hstmt;  
  
// Set the SQL_ATTR_ROW_BIND_TYPE statement attribute to use column-wise   
// binding. 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.  
SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN, 0);  
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);  
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, 10, 0);  
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);  
  
// Bind arrays to the CustID, Name, Address, and Phone columns.  
SQLBindCol(hstmt, 1, SQL_C_ULONG, CustIDArray, 0, CustIDIndArray);  
SQLBindCol(hstmt, 2, SQL_C_CHAR, NameArray, sizeof(NameArray[0]), NameLenOrIndArray);  
SQLBindCol(hstmt, 3, SQL_C_CHAR, AddressArray, sizeof(AddressArray[0]),  
            AddressLenOrIndArray);  
SQLBindCol(hstmt, 4, SQL_C_CHAR, PhoneArray, sizeof(PhoneArray[0]),  
            PhoneLenOrIndArray);  
  
// Execute a statement to retrieve rows from the Customers table.  
SQLExecDirect(hstmt, "SELECT CustID, Name, Address, Phone FROM Customers", SQL_NTS);  
  
// Fetch and display the first 10 rows.  
rc = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0);  
DisplayData(CustIDArray, CustIDIndArray, NameArray, NameLenOrIndArray, AddressArray,  
            AddressLenOrIndArray, PhoneArray, PhoneLenOrIndArray, RowStatusArray);  
  
// Call GetAction to get an action and a row number from the user.  
while (GetAction(&Action, &RowNum)) {  
   switch (Action) {  
  
      case SQL_FETCH_NEXT:  
      case SQL_FETCH_PRIOR:  
      case SQL_FETCH_FIRST:  
      case SQL_FETCH_LAST:  
      case SQL_FETCH_ABSOLUTE:  
      case SQL_FETCH_RELATIVE:  
         // Fetch and display the requested data.  
         SQLFetchScroll(hstmt, Action, RowNum);  
         DisplayData(CustIDArray, CustIDIndArray,  
                     NameArray, NameLenOrIndArray,  
                     AddressArray, AddressLenOrIndArray,  
                     PhoneArray, PhoneLenOrIndArray, RowStatusArray);  
         break;  
  
      case UPDATE_ROW:  
         // Place the new data in the rowset buffers and update the   
         // specified row.  
         GetNewData(&CustIDArray[RowNum - 1], &CustIDIndArray[RowNum - 1],  
                  NameArray[RowNum - 1], &NameLenOrIndArray[RowNum - 1],  
                  AddressArray[RowNum - 1], &AddressLenOrIndArray[RowNum - 1],  
                  PhoneArray[RowNum - 1], &PhoneLenOrIndArray[RowNum - 1]);  
         SQLSetPos(hstmt, RowNum, SQL_UPDATE, SQL_LOCK_NO_CHANGE);  
         break;  
  
      case DELETE_ROW:  
         // Delete the specified row.  
         SQLSetPos(hstmt, RowNum, SQL_DELETE, SQL_LOCK_NO_CHANGE);  
         break;  
  
      case ADD_ROW:  
         // Place the new data in the rowset buffers at index 10.   
         // This is an extra element for new rows so rowset data is   
         // not overwritten. Insert the new row. Row 11 corresponds   
         // to index 10.  
         GetNewData(&CustIDArray[10], &CustIDIndArray[10],  
                     NameArray[10], &NameLenOrIndArray[10],  
                     AddressArray[10], &AddressLenOrIndArray[10],  
                     PhoneArray[10], &PhoneLenOrIndArray[10]);  
         SQLSetPos(hstmt, 11, SQL_ADD, SQL_LOCK_NO_CHANGE);  
         break;  
   }  
}  
  
// Close the cursor.  
SQLCloseCursor(hstmt);