Клаузата FOR UPDATE извежда грешка в програмата esql

Разработваме програма за миграция. В DB има близо 80 милиона записа. Кодът е както следва:

static int mymigration(struct progargs *args) 
{
  exec sql begin declare section;
    const char *selectQuery;
    const char *updateQuery;
    long cur_start;
    long cur_end;
    long serial;
    long number;
    char frequency[3];
  exec sql end declare section;

    selectQuery = "select * from mytable where number >= ? and number <= ? for update of frequency ,status";
    updateQuery = "update mytable set frequency = ?, "
    " status = ? "
    " where current of my_cursor";

    cur_start= args->start;
    cur_end = args->end;

    exec sql prepare my_select_query from :selectQuery;
    /* Verify the sql code for error here */

    exec sql declare my_select_cursor cursor with hold for my_select_query;

    exec sql open my_select_cursor using :cur_start, :cur_end;
    /* Verify the sql code for error here */

    exec sql prepare my_update_query from :updateQuery;
    /* Verify the sql code for error here */        

    while (1)
    {
            number = 0;
            serial = 0;
            memset(frequency,0,sizeof(frequency));

            exec sql fetch my_select_cursor into number,:serial,:frequency;
            if (sqlca.sqlcode != SQL_OK)
                    break;            

            exec sql execute my_update_query using :frequency, :frequency;

    }      
    exec sql close my_select_trade_cursor;

}

Докато прилагаме това, получаваме съобщение за грешка „-255“. Намерихме едно решение за добавяне на работа и ангажиране на работа. Тъй като имаме голямо количество данни, това може да претрупа регистъра на транзакциите.

Има ли друго налично решение за този проблем? Уебсайтът на IBM за informix показва, че използването е правилно.

Оценявайте помощта предварително.

Благодаря, Матю Лиджу


person Liju Mathew    schedule 22.02.2010    source източник
comment
Memset() е излишен. Ако всичко, което искате да направите, е да зададете стойностите на честотата и състоянието на нула, защо не направите прост оператор без извличане: UPDATE MyTable SET (frequency, status) = (0, 0);? Можете да добавите 'WHERE номер ›=? И число ‹= ?' клауза също, ако имате нужда от нея (с 80 милиона реда вероятно е препоръчително).   -  person Jonathan Leffler    schedule 22.02.2010
comment
Показахме това като пример, но всъщност има някаква логика, която трябва да се направи върху стойността. В момента има само 1 колона с честота. Трябва да разделим данните по честота в колони за честота и състояние. Например: ако честотата е 1, трябва да зададем 01 на честота и 00 на състояние. Така че трябва да го правим при всяка транскация.   -  person Liju Mathew    schedule 23.02.2010


Отговори (1)


Грешка -255 е „Не е в транзакция“.

Не виждам изрази ЗАПОЧВАНЕ НА РАБОТА (или ИЗПЪЛНЕНИЕ НА РАБОТА или ВЪЗСТАНОВЯВАНЕ НА РАБОТА).

Трябва да добавите BEGIN WORK, преди да отворите курсора с клаузата FOR UPDATE. След това трябва да решите дали да се ангажирате периодично, за да избегнете прекалено дълги транзакции. Фактът, че използвате курсора FOR HOLD, показва, че сте мислили за използването на подтранзакции; ако нямаше да го направиш, нямаше да използваш тази клауза.

Обърнете внимание, че Informix има 3 основни режима на регистриране на база данни:

  • Нерегистриран (няма поддръжка за транзакции)
  • Регистриран (по подразбиране всеки израз е единична транзакция; изрично BEGIN WORK стартира транзакция с множество изрази, прекратена от COMMIT WORK или ROLLBACK WORK).
  • Записан MODE ANSI (малко опростено, вие автоматично сте в транзакция; имате нужда от изричен COMMIT или ROLLBACK, за да прекратите транзакция и след това може, по избор, да използвате изричен BEGIN, но BEGIN всъщност не е необходим).

От симптомите, които описвате, имате регистрирана, но не MODE ANSI база данни. Следователно, трябва изрично да кодирате изразите BEGIN WORK.

person Jonathan Leffler    schedule 22.02.2010