Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Приложения могут обновлять или удалять текущую строку в результирующем наборе с помощью размещенной инструкции обновления или удаления. Позиционированные инструкции UPDATE и DELETE поддерживаются некоторыми источниками данных, но не всеми. Чтобы определить, поддерживает ли источник данных операторы позиционированного обновления и удаления, приложение вызывает SQLGetInfo с типом сведений SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 или SQL_STATIC_CURSOR_ATTRIBUTES1 InfoType (в зависимости от типа курсора). Обратите внимание, что библиотека курсоров 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 идентификатор= столбца {выражение | NULL}
[,идентификатор= столбца {expression | NULL}]...
WHERE CURRENT OFCURSOR-name
DELETE FROMtable-nameWHERE CURRENT OFcursor-name
Обратите внимание, что для этих инструкций требуется имя курсора. Приложение либо может указать имя курсора с помощью SQLSetCursorName перед выполнением оператора, который создает результирующий набор, либо может позволить источнику данных автоматически сгенерировать имя курсора при создании курсора. В последнем случае приложение извлекает это имя курсора для использования в операторах позиционированного обновления и удаления, вызывая SQLGetCursorName.
Например, следующий код позволяет пользователю прокручивать таблицу "Клиенты" и удалять записи клиентов или обновлять их адреса и номера телефонов. Он вызывает SQLSetCursorName, чтобы указать имя курсора перед созданием результирующего набора клиентов, и использует три дескриптора операторов: hstmtCust для результирующего набора, hstmtUpdate для оператора позиционированного обновления и hstmtDelete для оператора позиционированного удаления. Хотя код может привязывать отдельные переменные к параметрам в инструкции позиционированного обновления, он обновляет буферы набора строк и привязывает элементы этих буферов. Это позволяет буферам набора строк синхронизироваться с обновленными данными.
#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);