Share via


Atualizar linhas no conjunto de linhas com SQLSetPos

A operação de atualização do SQLSetPos faz com que a fonte de dados atualize uma ou mais linhas selecionadas de uma tabela, usando dados nos buffers do aplicativo para cada coluna acoplada (a menos que o valor no buffer de comprimento/indicador seja SQL_COLUMN_IGNORE). As colunas que não estiverem associadas não serão atualizadas.

Para atualizar linhas com SQLSetPos, o aplicativo faz isto:

  1. Coloca novos valores dos dados nos buffers do conjunto de linhas. Para obter informações sobre como enviar dados longos usando SQLBulkOperations, confira Dados longos e SQLSetPos e SQLBulkOperations.

  2. Define o valor no buffer de comprimento/indicador de cada coluna conforme o necessário. Esse é o comprimento de byte dos dados ou SQL_NTS para colunas vinculadas a buffers de cadeia de caracteres, o comprimento de byte dos dados para colunas vinculadas a buffers binários e SQL_NULL_DATA para todas as colunas a serem definidas como NULL.

  3. Define o valor no buffer de comprimento/indicador daquelas colunas que não devem ser atualizadas para SQL_COLUMN_IGNORE. Embora o aplicativo possa ignorar essa etapa e reenviar os dados, isso é ineficiente e acarreta o risco de enviar valores para a fonte de dados que foram truncados ao serem lidos.

  4. Chama SQLSetPos com Operation definido como SQL_UPDATE e RowNumber definido como o número da linha a atualizar. Se RowNumber for 0, todas as linhas do conjunto de linhas serão atualizadas.

Depois que o SQLSetPos retorna, a linha atual é definida como a linha atualizada.

Ao atualizar todas as linhas do conjunto de linhas (RowNumber é igual a 0), um aplicativo pode desabilitar a atualização de determinadas linhas definindo os elementos correspondentes da matriz de operação de linha (apontados pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR) como SQL_ROW_IGNORE. A matriz de operação da linha corresponde em tamanho e número de elementos à matriz de status de linha (apontada pelo atributo de instrução SQL_ATTR_ROW_STATUS_PTR). Para atualizar apenas as linhas no conjunto de resultados cujo fetch foi efetuado com êxito e não foram excluídas do conjunto de linhas, o aplicativo usa a matriz de status de linha da função que efetuou fetch do conjunto de linhas como a matriz de operação de linha para SQLSetPos.

Para cada linha enviada à fonte de dados como uma atualização, os buffers de aplicativo precisam ter dados de linha válidos. Se os buffers do aplicativo tiverem sido preenchidos efetuando fetch e se uma matriz de status de linha tiver sido mantida, seus valores em cada uma das novas posições não deverão ser SQL_ROW_DELETED, SQL_ROW_ERROR ou SQL_ROW_NOROW.

Por exemplo, o código a seguir permite que o usuário role na tabela Clientes e atualize, exclua ou adicione linhas. Ele coloca os dados novos nos buffers do conjunto de linhas antes de chamar SQLSetPos para atualizar ou adicionar linhas. Uma linha extra é alocada no final dos buffers do conjunto de linhas para manter novas linhas. Isso impede que os dados existentes sejam substituídos quando os dados de uma nova linha são colocados nos buffers.

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