현재 위치 업데이트 및 Delete 문

애플리케이션은 위치가 지정된 업데이트 또는 삭제 문을 사용하여 결과 집합의 현재 행을 업데이트하거나 삭제할 수 있습니다. 위치가 지정된 업데이트 및 삭제 문은 일부 데이터 원본에서 지원되지만 모두 지원되지는 않습니다. 데이터 원본이 위치 지정 업데이트 및 삭제 문을 지원하는지 여부를 확인하기 위해 애플리케이션은 커서 유형에 따라 SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 또는 SQL_STATIC_CURSOR_ATTRIBUTES1 InfoType을 사용하여 SQLGetInfo를 호출합니다. ODBC 커서 라이브러리는 위치가 지정된 업데이트 및 삭제 문을 시뮬레이트합니다.

배치된 업데이트 또는 삭제 문을 사용하려면 애플리케이션이 SELECT FOR UPDATE 문을 사용하여 결과 집합을 만들어야 합니다. 이 문의 구문은 다음과 같습니다.

SELECT [ALL | DISTINCT] select-list

FROMtable-reference-list

[WHERE검색 조건]

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

그런 다음 애플리케이션은 업데이트 또는 삭제할 행에 커서를 배치합니다. SQLFetchScroll을 호출하여 필요한 행이 포함된 행 집합을 검색하고 SQLSetPos를 호출하여 행 집합 커서를 해당 행에 배치하면 됩니다. 그런 다음 애플리케이션은 결과 집합에서 사용하는 문과 다른 문에서 위치가 지정된 update 또는 delete 문을 실행합니다. 이러한 문의 구문은 다음과 같습니다.

UPDATE테이블 이름

SET열 식별자= {expression | NULL}

[,column-identifier= {expression | NULL}]...

WHERE CURRENT OFcursor-name

DELETE FROMtable-nameWHERE CURRENT OFcursor-name

이러한 문에는 커서 이름이 필요합니다. 애플리케이션은 결과 집합을 만드는 문을 실행하기 전에 SQLSetCursorName을 사용하여 커서 이름을 지정하거나 커서를 만들 때 데이터 원본이 자동으로 커서 이름을 생성하도록 할 수 있습니다. 후자의 경우 애플리케이션은 SQLGetCursorName을 호출하여 위치가 지정된 업데이트 및 삭제 문에 사용할 커서 이름을 검색합니다.

예를 들어 다음 코드를 사용하면 사용자가 Customers 테이블을 스크롤하여 고객 레코드를 삭제하거나 주소와 전화 번호를 업데이트할 수 있습니다. SQLSetCursorName을 호출하여 고객 결과 집합을 만들기 전에 커서 이름을 지정하고 결과 집합에 대한 hstmtCust, 배치된 업데이트 문의 hstmtUpdate위치가 지정된 delete 문의 hstmtDelete라는 세 개의 문 핸들을 사용합니다. 코드는 배치된 update 문의 매개 변수에 별도의 변수를 바인딩할 수 있지만 행 집합 버퍼를 업데이트하고 이러한 버퍼의 요소를 바인딩합니다. 이렇게 하면 업데이트된 데이터와 동기화된 행 집합 버퍼가 유지됩니다.

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