Как указать список выражений переменных в запросе Pro*C?
У меня проблема с запросом 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 настолько велика, что я не знаю, где искать. Я пробовал разные способы, но ни один не работал.
РЕДАКТИРОВАТЬ ОК, я нашел решение, которое работает. Это не элегантно, это не продвинуто, но работает хорошо. Я помещаю список предложений 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 ответа
Вы не можете сделать это без Oracle Dynamic SQL. Вам нужно будет создать предложение IN во время выполнения и выполнить EXECUTE IMMEDIATE. По крайней мере, вы можете использовать метод 1, основанный на ваших запросах.
Ранее я использовал таблицу, состоящую из идентификатора и набора строк, где строки представляют собой перестановку возможных значений в списке "in". Затем я присоединяюсь к таблице на основе идентификатора, и он дает мне результаты, которые мне нужны.
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 ... и вставить его в соединение.
... Main String:= 'Выбрать * ИЗ таблицы, ГДЕ id=:uniqid И язык IN'; - можно разделить на две части:uniqd ... Выбрать Language_code для v_string из x_table; цикл Copy & Concat v_string в LanCode_String и с ' ',; концевой цикл;.. Конкат Lancode для главной строки... Подготовить и выполнить главную строку.