Pernyataan Pembaruan dan Penghapusan yang Diposisikan

Aplikasi dapat memperbarui atau menghapus baris saat ini dalam tataan hasil dengan pernyataan pembaruan atau penghapusan yang diposisikan. Pernyataan pembaruan dan penghapusan yang diposisikan didukung oleh beberapa sumber data, tetapi tidak semuanya. Untuk menentukan apakah sumber data mendukung pernyataan pembaruan dan penghapusan yang diposisikan, aplikasi memanggil SQLGetInfo dengan SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1, atau SQL_STATIC_CURSOR_ATTRIBUTES1 InfoType (tergantung pada jenis kursor). Perhatikan bahwa pustaka kursor ODBC mensimulasikan pernyataan pembaruan dan penghapusan yang diposisikan.

Untuk menggunakan pernyataan pembaruan atau penghapusan yang diposisikan, aplikasi harus membuat tataan hasil dengan pernyataan SELECT FOR UPDATE . Sintaks pernyataan ini adalah:

PILIH [ALL | DISTINCT] select-list

FROMtable-reference-list

[WHEREsearch-condition]

FOR UPDATE OF [column-name [,column-name]...]

Aplikasi kemudian memposisikan kursor pada baris yang akan diperbarui atau dihapus. Ini dapat dilakukan dengan memanggil SQLFetchScroll untuk mengambil set baris yang berisi baris yang diperlukan dan memanggil SQLSetPos untuk memosisikan kursor set baris pada baris tersebut. Aplikasi kemudian menjalankan pernyataan pembaruan atau penghapusan yang diposisikan pada pernyataan yang berbeda dari pernyataan yang digunakan oleh kumpulan hasil. Sintaks dari pernyataan ini adalah:

PERBARUInama tabel

SETpengidentifikasi= kolom {expression | NULL}

[,pengidentifikasi= kolom {expression | NULL}]...

WHERE CURRENT OFcursor-name

HAPUS DARInamatabel DI MANA CURRENT OFcursor-name

Perhatikan bahwa pernyataan ini memerlukan nama kursor. Aplikasi dapat menentukan nama kursor dengan SQLSetCursorName sebelum menjalankan pernyataan yang membuat kumpulan hasil atau dapat membiarkan sumber data secara otomatis menghasilkan nama kursor saat kursor dibuat. Dalam kasus terakhir, aplikasi mengambil nama kursor ini untuk digunakan dalam pernyataan pembaruan dan penghapusan yang diposisikan dengan memanggil SQLGetCursorName.

Misalnya, kode berikut memungkinkan pengguna untuk menggulir tabel Pelanggan dan menghapus rekaman pelanggan atau memperbarui alamat dan nomor telepon mereka. Ini memanggil SQLSetCursorName untuk menentukan nama kursor sebelum membuat kumpulan hasil pelanggan dan menggunakan tiga handel pernyataan: hstmtCust untuk kumpulan hasil, hstmtUpdate untuk pernyataan pembaruan yang diposisikan, dan hstmtDelete untuk pernyataan penghapusan yang diposisikan. Meskipun kode dapat mengikat variabel terpisah ke parameter dalam pernyataan pembaruan yang diposisikan, kode tersebut memperbarui buffer set baris dan mengikat elemen buffer ini. Ini membuat buffer set baris tetap sinkron dengan data yang diperbarui.

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