Pozicované příkazy pro aktualizaci a odstranění

Aplikace mohou aktualizovat nebo odstranit aktuální řádek v sadě výsledků pomocí příkazu umístěné aktualizace nebo odstranění. Některé zdroje dat podporují umístěné příkazy aktualizace a odstranění, ale ne všechny. Pokud chcete zjistit, zda zdroj dat podporuje poziční aktualizační a delete příkazy, aplikace volá SQLGetInfo pomocí SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 nebo SQL_STATIC_CURSOR_ATTRIBUTES1 InfoType (v závislosti na typu kurzoru). Upozorňujeme, že knihovna kurzorů ODBC simuluje umístěné příkazy update a delete.

Chcete-li použít umístěný příkaz update nebo delete, musí aplikace vytvořit sadu výsledků pomocí příkazu SELECT FOR UPDATE . Syntaxe tohoto příkazu je:

SELECT [ALL | DISTINCT] select-list

FROMseznam-referencí-tabulky

[WHERE– podmínka hledání]

PRO AKTUALIZACI [column-name [,column-name]...]

Aplikace pak umístí kurzor na řádek, který se má aktualizovat nebo odstranit. To lze provést voláním SQLFetchScroll načíst sadu řádků obsahující požadovaný řádek a voláním SQLSetPos umístit kurzor sady řádků na tento řádek. Aplikace pak spustí umístěný příkaz update nebo delete na jiném příkazu, než který používá sada výsledků. Syntaxe těchto příkazů je:

AKTUALIZOVATnázev tabulky

SETcolumn-identifier= {expression | NULL}

[,identifikátor sloupce= {expression | NULL}]...

WHERE CURRENT OFcursor-name

DELETE FROMtable-nameWHERE CURRENT OFcursor-name

Všimněte si, že tyto příkazy vyžadují název kurzoru. Aplikace může buď zadat název kurzoru pomocí SQLSetCursorName před spuštěním příkazu, který vytvoří sadu výsledků, nebo může zdroj dat automaticky vygenerovat název kurzoru při vytvoření kurzoru. V druhém případě aplikace načte tento název kurzoru pro použití v umístěných aktualizačních a delete příkazech voláním SQLGetCursorName.

Následující kód například umožňuje uživateli procházet tabulku Zákazníci a odstraňovat záznamy zákazníků nebo aktualizovat jejich adresy a telefonní čísla. Volá SQLSetCursorName k určení názvu kurzoru před vytvořením sady výsledků zákazníků a používá tři popisovače příkazů: hstmtCust pro sadu výsledků, hstmtUpdate pro umístěný aktualizační příkaz a hstmtDelete pro umístěný příkaz delete. I když kód může svázat samostatné proměnné s parametry v příkazu pro aktualizaci s určením pozice, aktualizuje paměti sady řádků a svazuje prvky těchto pamětí. Vyrovnávací paměti sady řádků se tím synchronizují s aktualizovanými daty.

#define POSITIONED_UPDATE 100  
#define POSITIONED_DELETE 101  
  
SQLUINTEGER    CustIDArray[10];  
SQLCHAR        NameArray[10][51], AddressArray[10][51],   
               PhoneArray[10][11];  
SQLINTEGER     CustIDIndArray[10], NameLenOrIndArray[10],   
               AddressLenOrIndArray[10],  
               PhoneLenOrIndArray[10];  
SQLUSMALLINT   RowStatusArray[10], Action, RowNum;  
SQLHSTMT       hstmtCust, hstmtUpdate, hstmtDelete;  
  
// Set the SQL_ATTR_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(hstmtCust, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);  
SQLSetStmtAttr(hstmtCust, SQL_ATTR_ROW_ARRAY_SIZE, 10, 0);  
SQLSetStmtAttr(hstmtCust, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);  
  
// Bind arrays to the CustID, Name, Address, and Phone columns.  
SQLBindCol(hstmtCust, 1, SQL_C_ULONG, CustIDArray, 0, CustIDIndArray);  
SQLBindCol(hstmtCust, 2, SQL_C_CHAR, NameArray, sizeof(NameArray[0]),  
            NameLenOrIndArray);  
SQLBindCol(hstmtCust, 3, SQL_C_CHAR, AddressArray, sizeof(AddressArray[0]),  
         AddressLenOrIndArray);  
SQLBindCol(hstmtCust, 4, SQL_C_CHAR, PhoneArray, sizeof(PhoneArray[0]),  
            PhoneLenOrIndArray);  
  
// Set the cursor name to Cust.  
SQLSetCursorName(hstmtCust, "Cust", SQL_NTS);  
  
// Prepare positioned update and delete statements.  
SQLPrepare(hstmtUpdate,  
   "UPDATE Customers SET Address = ?, Phone = ? WHERE CURRENT OF Cust",  
   SQL_NTS);  
SQLPrepare(hstmtDelete, "DELETE FROM Customers WHERE CURRENT OF Cust", SQL_NTS);  
  
// Execute a statement to retrieve rows from the Customers table.  
SQLExecDirect(hstmtCust,  
   "SELECT CustID, Name, Address, Phone FROM Customers FOR UPDATE OF Address, Phone",  
   SQL_NTS);  
  
// Fetch and display the first 10 rows.  
SQLFetchScroll(hstmtCust, 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(hstmtCust, Action, RowNum);  
         DisplayData(CustIDArray, CustIDIndArray, NameArray, NameLenOrIndArray,  
                     AddressArray, AddressLenOrIndArray, PhoneArray,  
                     PhoneLenOrIndArray, RowStatusArray);  
         break;  
  
      case POSITIONED_UPDATE:  
         // Get the new data and place it in the rowset buffers.  
         GetNewData(AddressArray[RowNum - 1], &AddressLenOrIndArray[RowNum - 1],  
                     PhoneArray[RowNum - 1], &PhoneLenOrIndArray[RowNum - 1]);  
  
         // Bind the elements of the arrays at position RowNum-1 to the   
         // parameters of the positioned update statement.  
         SQLBindParameter(hstmtUpdate, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,  
                           50, 0, AddressArray[RowNum - 1], sizeof(AddressArray[0]),  
                           &AddressLenOrIndArray[RowNum - 1]);  
         SQLBindParameter(hstmtUpdate, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,  
                           10, 0, PhoneArray[RowNum - 1], sizeof(PhoneArray[0]),  
                           &PhoneLenOrIndArray[RowNum - 1]);  
  
         // Position the rowset cursor. The rowset is 1-based.  
         SQLSetPos(hstmtCust, RowNum, SQL_POSITION, SQL_LOCK_NO_CHANGE);  
  
         // Execute the positioned update statement to update the row.  
         SQLExecute(hstmtUpdate);  
         break;  
  
      case POSITIONED_DELETE:  
         // Position the rowset cursor. The rowset is 1-based.  
         SQLSetPos(hstmtCust, RowNum, SQL_POSITION, SQL_LOCK_NO_CHANGE);  
  
         // Execute the positioned delete statement to delete the row.  
         SQLExecute(hstmtDelete);  
         break;  
   }  
}  
  
// Close the cursor.  
SQLCloseCursor(hstmtCust);