информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Страшный баг в WindowsАтака на InternetВсе любят мед
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Извиняюсь за тупость, но Вы про что? 10.09.08 14:13  Число просмотров: 1199
Автор: Vedrus <Serokhvostov Anton> Статус: Member
Отредактировано 10.09.08 14:14  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
Извиняюсь за тупость, но Вы про что?
У меня база данных Microsoft Access. Я просто пытаюсь прочитать таблицу.
Если это важно – вот запрос:
SELECT id_Fancy, title, descr, comment
FROM fancy
ORDER BY title

---
<programming>
[Win32] Повторное выполнение запроса SQLExecDirect или SQLExecute 10.09.08 07:19  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Первый раз функция отрабатывает нормально и возвращает необходимые данные. При повторном вызове выдаёт ошибку «24000» (Недопустимое состояние курсора). В MSDN прочитал, что эта ошибка возникает, пока SQLFetch не вернёт SQL_NO_DATA, т.е. пока данные не кончатся. Прогнал SQLFetch’ем все данные, но результат тот же.

Повторное исполнение запросов нужно из-за того, что таблица обновляется и нужно получать актуальные данные. Надеюсь на помощь.
[Win32] [ODBC API] Без листинга вызовов функций трудно даже представить в чем может быть проблема. 10.09.08 11:31  
Автор: Den <Denis> Статус: The Elderman
<"чистая" ссылка> <обсуждение закрыто>
> Первый раз функция отрабатывает нормально и возвращает
> необходимые данные. При повторном вызове выдаёт ошибку
> «24000» (Недопустимое состояние курсора). В MSDN прочитал,
> что эта ошибка возникает, пока SQLFetch
> не вернёт SQL_NO_DATA, т.е. пока данные не кончатся.
> Прогнал SQLFetch’ем все данные, но
> результат тот же.

У тебя первым запросом создается курсор на сервере?

> Повторное исполнение запросов нужно из-за того, что таблица
> обновляется и нужно получать актуальные данные. Надеюсь на
> помощь.

Т.е. нужно обновлять набор записей клиента привязанного к открытому на сервере курсору?
Извиняюсь за тупость, но Вы про что? 10.09.08 14:13  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
Отредактировано 10.09.08 14:14  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
Извиняюсь за тупость, но Вы про что?
У меня база данных Microsoft Access. Я просто пытаюсь прочитать таблицу.
Если это важно – вот запрос:
SELECT id_Fancy, title, descr, comment
FROM fancy
ORDER BY title

---
Сам SQL запрос мне ни о чем не говорит. [upd] 10.09.08 14:25  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 10.09.08 14:42  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
Сам SQL запрос мне ни о чем не говорит.
Для анализа нужен порядок вызовов функций API - SQLPrepare, SQLExecDirect, SQLExecute, SQLFetch
Приведи листинг программы. Какой язык-то хоть? VBA?

Проблема может быть в том, что ты пытаешься запустить на выполнение запрос через тот же handle, что и предыдущий запрос, который еще в состоянии выполнения или получения данных.

[upd]
Последнее легко проверить, если после получения данных и выполнения SQLCloseCursor(hstmt) SQLSTATE будет в значении 24000, то это означает, что курсор предыдущего запроса закрыт.
<без заголовка> 10.09.08 16:41  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
Отредактировано 10.09.08 16:43  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
	// Выделить память для идентификатора окружения //
	if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_ENV, SQL_HANDLE_NULL, &m_hEnv))
		return FALSE;
	// Выбрать версию ODBC //
	if (SQL_SUCCESS != SQLSetEnvAttr(m_hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, NULL))
		return FALSE;
	// Выделить память для идентификатора подключения Fancy //
	if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_DBC, m_hEnv, &m_hFancyConnect))
		return FALSE;
	// Выделить память для идентификатора подключения Subscriebe //
	if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_DBC, m_hEnv, &m_hSubscriebeConnect))
		return FALSE;
	// Подключиться к источнику данных Fancy //
	if (SQL_SUCCESS != SQLDriverConnect(m_hFancyConnect, NULL,
(SQLTCHAR *) cszFANCY_DSN , SQL_NTS, (SQLTCHAR *) szoutDSN, MAX_DSN_SIZE, &dwOutStringLength, SQL_DRIVER_COMPLETE))
		return FALSE;
	if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, m_hFancyConnect, &m_hStmtFancy))
		return FALSE;
	ret = SQLSetStmtAttr(m_hStmtFancy, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_STATIC, SQL_IS_INTEGER);
	if (SQL_SUCCESS != ret && SQL_SUCCESS_WITH_INFO != ret)
		return FALSE;
	if (SQL_SUCCESS != SQLBindCol(m_hStmtFancy, 1, SQL_C_LONG, &m_Fancy.dwid_Fancy, 4, &dwDataLength))
		return FALSE;
	if (SQL_SUCCESS != SQLBindCol(m_hStmtFancy, 2, SQL_C_CHAR, m_Fancy.szTitle, MAX_TITLE_SIZE, &dwDataLength))
		return FALSE;
	if (SQL_SUCCESS != SQLBindCol(m_hStmtFancy, 3, SQL_C_CHAR, m_Fancy.szDescr, MAX_DESCR_SIZE, &dwDataLength))
		return FALSE;
	if (SQL_SUCCESS != SQLBindCol(m_hStmtFancy, 4, SQL_C_CHAR, m_Fancy.szComnt, MAX_COMNT_SIZE, &dwDataLength))
		return FALSE;
	if (SQL_SUCCESS != SQLBindCol(m_hStmtFancy, 5, SQL_C_LONG, &m_Fancy.dwTLong, 4, &dwDataLength))
		return FALSE;
	if (SQL_SUCCESS != SQLBindCol(m_hStmtFancy, 6, SQL_C_LONG, &m_Fancy.dwDatTim, 4, &dwDataLength))
		return FALSE;
	if (SQL_SUCCESS != SQLBindCol(m_hStmtFancy, 7, SQL_C_LONG, &m_Fancy.dwPeriod, 4, &dwDataLength))
		return FALSE;
	if (SQL_SUCCESS != SQLBindCol(m_hStmtFancy, 8, SQL_C_LONG, &m_Fancy.dwTLast, 4, &dwDataLength))
		return FALSE;
	if (SQL_SUCCESS != SQLPrepare(m_hStmtFancy, (SQLTCHAR *) cszSTMT_FANCY, SQL_NTS))
		return FALSE;
	if (SQL_SUCCESS != SQLExecute(m_hStmtFancy))
		return FALSE;

---

Вот такой код. Я понимаю, что здесь без SQLPrepare обойтись можно, но для единообразия с остальными запросами сделал так. Если в конец добавить ещё один SQLExecute, то образуется ошибка 24000.

Если между вызовами SQLExecute вставить SQLCloseCursor, то всё отлично. Это как раз та функция что мне была нужна, спасибо за помощь.

Получается, перед каждым выполнением запроса я вызываю SQLCloseCursor. Так делать правильно, или что-то умнее есть?
Без SQL Prepare, конечно, можно обойтись... 10.09.08 18:30  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 10.09.08 18:30  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
> Вот такой код. Я понимаю, что здесь без SQLPrepare обойтись
> можно, но для единообразия с остальными запросами сделал
> так. Если в конец добавить ещё один SQLExecute, то
> образуется ошибка 24000.

Без SQL Prepare, конечно, можно обойтись...
Но так как ты постоянно используешь некоторый SQL запрос для получения свежих данных из БД, то SQLPrepare лучше оставить для ускорения выполнения запроса.
Только есть один важный момент - так как ты используешь процедурное программирование, то для хранения StatementHandles часто выполняющихся SQL запросов и их состояний "prepared" лучше использовать статические или глобальные переменные. В таком случае, для выполения SQL запроса ты сможешь проверить состояние IsPrepared и если оно "TRUE", то сразу запустить SQLExecute без SQLPrepare (естественно, что SQLPrepare в таком случае должен выполнятся на этапе инициализации приложения).

> Если между вызовами SQLExecute вставить SQLCloseCursor, то
> всё отлично. Это как раз та функция что мне была нужна,
> спасибо за помощь.

Так и должно быть. Курсор никогда сам не закрывается, за исключением случаев использования ручного управления транзакциями.

> Получается, перед каждым выполнением запроса я вызываю
> SQLCloseCursor. Так делать правильно, или что-то умнее
> есть?

Только не перед каждым, а после каждого (если запрос возвращает данные) ;)
Спасибо за компетентное разъяснение. 11.09.08 01:59  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach