Win API & ODBC (отказ в создании записи )
От: NdF  
Дата: 12.11.05 14:57
Оценка:
Возник такой вопрос. В БД (Access 2000) заносятся записи со скоростью приблизительно 8 записей в секунду (+- 3 записи). Записи успешно добавляются, вот код для их добавления
char *szQueryY="INSERT INTO `Y_Table` (`Num`,`WorkTime`,`Y`) VALUES (?,?,?);";
char *szQueryI="INSERT INTO `I_Table` (`Num`,`WorkTime`,`I`) VALUES (?,?,?);";
char *szQuery;

           switch(table)
           {
           case 'Y':szQuery=szQueryY; break;
           case 'I':szQuery=szQueryI; break;
           default: return false;                
           }
    
SQLPrepare(hstmt, (UCHAR*)szQuery, SQL_NTS); 


SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_INTEGER, 
    SQL_INTEGER, 1, 0, &Num, 0, 0); 

SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_DOUBLE,   
    SQL_C_DOUBLE, 1, 0, &Time, 0, 0); 

SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_DOUBLE, 
    SQL_C_DOUBLE, 1, 0, &mean, 0, 0);

if(SQLExecute(hstmt)==SQL_ERROR)
{
     return false;
}

return true ;

}


Как я сказал, записи добавляются успешно. Но я немного лукавлю. Есть проблема, время от времени SQLExecute() возвращает SQL_ERROR. При этом входные данные подаются корректные (т.е. практически ничем не отличаются от тех, на которых SQL_Execute нормально отрабатывала). Никакой закономерности по времени и по входным данным не обнаружено. Т.е. я не могу сказать, что каждые 2 минуты происходит ошибка или при каких-то определенных значениях. Но я могу сказать, что чем дольше работает прога, тем ошибки появляются чаще. У меня складывается ощущеие, что это зависит от размера БД. Чем больше в ней записей, тем чаще ошибки. Если БД почистить, то некоторое время ошибки не выскакивают, но потом постепенно появляются, при этом как я говорил частота их появления возрастает.
Если БД не обнулять, но закрыть приложение, а потом опять запустить, то ошибки начинают выскакивать практически сразу (что косвенно подтверждает зависимость их появления от размеров БД)
У меня 2 вопроса:
1) Почему это происходит? Кто(что) в этом виноват?
2) Как с этим бороться? (Что делать? -Чернышевский).
Я пробовал подставить такой запрос
INSERT INTO `Y_Table` (`Num`,`WorkTime`,`Y`) VALUES (1,1,1);";
INSERT INTO `I_Table` (`Num`,`WorkTime`,`I`) VALUES (2,2,2);

Но ошибки все равно, время от времени выскакивали, что еще раз подтверждает, что дело не во входных даны.
Пробовал транзакции – добавлял в конце функции
SQLTransact(henv,hdbc,SQL_COMMIT);
Не помогло. Кстати эта функция нужна там или нет?
У меня есть на примете одно решение:
В случае, если запрос не удался делать Sleep() на 10-50мс и повторить запрос. Так до тех пор, пока запрос не проскочит, но не более 5 раз (к примеру, а то может и 2 или 10).
Но хотелось бы более элегантно решить эту проблему. К тому же попытка повторить запрос не гарантирует успех, т.к. уже пробовал повторять запрос второй раз в случае неудачи и бывало, что и второй раз подряд выскакивала ошибка.


Итак, работа происходит с БД – Microsoft Access 2000, используется ODBC (ну, я думаю, все догадались).

На всякий случай опишу структуру БД (а именно 2 таблицы, т.к. только в них трабблы):
№ Имя Тип
I_Table
1) Num счетчик (автоинкремент) Длинное целое
2) WorkTime Длинное целое
3) I Действительное

Y_Table
1) Num счетчик (автоинкремент) Длинное целое
2) WorkTime Действительное
3)Y Двойное с плавающей точкой

Структура БД не обсуждается .
Заранее спасибо за развернутые ответы.

P.s. Забыл написать как подключаюсь, мало ли пригодится
Codbc::Codbc()
{
                        //////////////
                        szUser[256] = 0;
                        szPass[256] = 0;
                        strcpy(szDsn,"mysource");
                        hstmt=NULL;
                        henv = NULL;
                        hdbc = NULL;
                        ///////////// 


if (::SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv) == SQL_ERROR)
{
   
   
    MessageBox(0,"error connect","error connect",0);
}

                 ::SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, 
                                (void*) SQL_OV_ODBC3, SQL_IS_INTEGER);

                                                     
                                     if ( ::SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc) == SQL_ERROR)
                                     {
                                       
                                      
                                       MessageBox(0,"error connect2","error connect2",0);
                                     }



if ( ::SQLConnect(hdbc, (SQLTCHAR*)szDsn, SQL_NTS,
        (SQLTCHAR*)szUser, _tcslen(szUser), (SQLTCHAR*)szPass, 
         _tcslen(szPass) ) == SQL_ERROR )
{
       
       
    MessageBox(0,"error connect source","error connect source",0);
}

                         if (::SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt) == SQL_ERROR)
            {
                 MessageBox(0,"Error zapros","Error zapros",0); 
                 
                
            }


}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.