Как указать список выражений переменных в запросе Pro * C? - PullRequest
0 голосов
/ 17 ноября 2009

У меня проблема с запросом Pro * C, который я пытаюсь оптимизировать.

Для объяснения наше приложение ищет строки в огромной базе данных. Эти строки существуют на нескольких языках, и старый код выбирал строку для каждого языка в массиве. Теперь, когда эти запросы являются наиболее трудоемкой частью нашего приложения, я хотел сделать только один запрос, который записывает непосредственно в массив.

Коды языков представляют собой двухбуквенные коды ISO-639 (en для английского, fr для французского).

Старый способ (это только упрощенный код, показывающий намерение)

struct ROW arr[MAX_LAN];
struct ROW_IND arr_ind[MAX_LAN];
uint_t LanIdx;
for(LanIdx=0; LanIdx<MAX_LAN; LanIdx++) {
  EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
      INTO :arr[LanIdx]:arr_ind[LanIdx]
      FROM table WHERE id=:uniqid AND language=:LanCode[LanIdx];
}

Я бы хотел сделать что-то вроде этого:

EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
    INTO :arr:arr_ind
    FROM table WHERE id=:uniqid AND language IN (:LanCodes);

но не знаю, как мне определить LanCodes.

Он работает с постоянным списком (время компиляции), как это

EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
    INTO :arr:arr_ind
    FROM table WHERE id=:uniqid AND language IN ('en','fr','de');

но это бесполезно, так как языки могут отличаться от случая к случаю.

Если я напишу что-то вроде

char LanCodes[MAX_LANS*5];
sprintf(LanCodes, "%s", LanCode[LanIdx]);

EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
    INTO :arr:arr_ind
    FROM table WHERE id=:uniqid AND language IN (:LanCodes);

работает, только если в строке 1 код языка.

Итак, мой вопрос: кто-нибудь знает, как заставить это работать? Документация по Oracle настолько велика, что я не знаю, где искать. Я пробовал разные способы, но ни один не работал.

EDIT Хорошо, я нашел решение, которое работает. Это не элегантно, это не продвинуто, но работает хорошо. Я добавил в свой запрос список предложений OR, и он возвращает то, что мне нужно, в нужной форме.

EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
    INTO :arr:arr_ind
    FROM table WHERE id=:uniqid AND (
                language=:v1[ 0] OR
                language=:v1[ 1] OR
                language=:v1[ 2] OR
                language=:v1[ 3] OR
                language=:v1[ 4] OR
                language=:v1[ 5] OR
                language=:v1[ 6] OR
                language=:v1[ 7] OR
                language=:v1[ 8] OR
                language=:v1[ 9] OR
                language=:v1[10] OR
                language=:v1[11] OR
                language=:v1[12] OR
                language=:v1[13] OR
                language=:v1[14] OR
                language=:v1[15] OR
                language=:v1[16] OR
                language=:v1[17] OR
                language=:v1[18] OR
                language=:v1[19] OR
                language=:v1[20] OR
                language=:v1[21] OR
                language=:v1[22] OR
                language=:v1[23] OR
                language=:v1[24] OR
                language=:v1[25] OR
                language=:v1[26] OR
                language=:v1[27] OR
                language=:v1[28] OR
                language=:v1[29] OR
                language=:v1[30]);

Это быстрее, когда есть более двух языков, поэтому я называю этот вариант или старый, в зависимости от количества языков для выборки.

Ответы [ 4 ]

1 голос
/ 17 ноября 2009

Вероятно, эта статья AskTom может вам помочь.

1 голос
/ 17 ноября 2009

Вы не можете сделать это без Oracle Dynamic SQL . Вам нужно будет создать предложение IN во время выполнения и выполнить EXECUTE IMMEDIATE. По крайней мере, вы можете использовать метод 1, основанный на ваших запросах.

0 голосов
/ 19 ноября 2009

... Основная строка: = 'Выбрать * ИЗ таблицы, ГДЕ id =: uniqid И язык IN'; - можно разделить на две части: uniqd ... Выберите Language_code в v_string из x_table; петля Скопируйте & Concat v_string в LanCode_String и с '',; концевой цикл; .. Concat Lancode для главной строки. .. Подготовьте и выполните основную строку.

0 голосов
/ 18 ноября 2009

Ранее я использовал таблицу, состоящую из идентификатора и набора строк, где строки представляют собой перестановку возможных значений в списке «in». Затем я присоединяюсь к таблице на основе ID, и это дает мне результаты, которые мне нужны.

create table permute (
  id number,
  lang char(2)
);
create index permute_p1 on permute ( lang, id );
insert into permute ( id, lang ) values ( 1, 'en' );
insert into permute ( id, lang ) values ( 2, 'en' );
insert into permute ( id, lang ) values ( 2, 'fr' );
...

Все, что вам нужно сделать, это выбрать правильное значение "ID" 2, 3, 4 ... и поместить его в присоединиться.

...