Aktualizace řádků v sadě řádků pomocí SQLSetPos

Operace aktualizace SQLSetPos zaktualizuje zdroj dat jeden nebo více vybraných řádků tabulky pomocí dat v vyrovnávací paměti aplikace pro každý vázaný sloupec (pokud hodnota v vyrovnávací paměti délky nebo indikátoru není SQL_COLUMN_IGNORE). Sloupce, které nejsou vázané, nebudou aktualizovány.

Chcete-li aktualizovat řádky pomocí SQLSetPos, aplikace provede následující:

  1. Umístí nové hodnoty dat do vyrovnávací paměti sady řádků. Informace o tom, jak odesílat dlouhá data pomocí SQLSetPos, naleznete v tématu Long Data a SQLSetPos a SQLBulkOperations.

  2. Nastaví hodnotu ve vyrovnávací paměti pro délku/indikátor každého sloupce podle potřeby. Jedná se o bajtovou délku dat nebo SQL_NTS pro sloupce vázané na vyrovnávací paměti řetězců, bajtovou délku dat pro sloupce vázané na binární vyrovnávací paměti a SQL_NULL_DATA pro všechny sloupce, které mají být nastaveny na hodnotu NULL.

  3. Nastaví hodnotu v vyrovnávací paměti délky a indikátoru těchto sloupců, které se neaktualizují na SQL_COLUMN_IGNORE. I když aplikace může tento krok přeskočit a znovu odeslat existující data, je to neefektivní a riziko odesílání hodnot do zdroje dat, které byly zkráceny při jejich čtení.

  4. Volá SQLSetPos s operací nastavenou na SQL_UPDATE a RowNumber nastaven na počet řádků, které chcete aktualizovat. Pokud je argument RowNumber 0, aktualizují se všechny řádky v sadě řádků.

Po vrácení sqlSetPos se aktuální řádek nastaví na aktualizovaný řádek.

Při aktualizaci všech řádků sady řádků (RowNumber je rovno 0), může aplikace zakázat aktualizaci určitých řádků nastavením odpovídajících prvků pole operace řádku (odkazované atributem příkazu SQL_ATTR_ROW_OPERATION_PTR) na SQL_ROW_IGNORE. Pole operace řádku odpovídá velikosti a počtu prvků stavové matici řádku (odkazované atributem příkazu SQL_ATTR_ROW_STATUS_PTR). Chcete-li aktualizovat pouze řádky v sadě výsledků, které byly úspěšně načteny a nebyly odstraněny ze sady řádků, aplikace používá pole stavu řádku z funkce, která načítala sadu řádků jako pole operace řádku do sqlSetPos.

Pro každý řádek, který je odeslán do zdroje dat jako aktualizace, by vyrovnávací paměti aplikace měly mít platná data řádku. Pokud byly vyrovnávací paměti aplikace vyplněny načtením a pokud bylo zachováno pole stavu řádku, neměly by být jeho hodnoty na každé z těchto pozic řádků SQL_ROW_DELETED, SQL_ROW_ERROR ani SQL_ROW_NOROW.

Následující kód například umožňuje uživateli procházet tabulku Zákazníci a aktualizovat, odstranit nebo přidat nové řádky. Před voláním sqlSetPos pro aktualizaci nebo přidání nových řádků umístí nová data do vyrovnávací paměti sady řádků. Na konci vyrovnávací paměti sady řádků je přidělen další řádek, který bude obsahovat nové řádky; tím zabráníte přepsání existujících dat při umístění dat pro nový řádek do vyrovnávací paměti.

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