Como especificar uma lista de expressão variável em uma consulta Pro*C?
-
20-09-2019 - |
Pergunta
Tenho um problema com uma consulta profissional que estou tentando otimizar.
Para explicar, nosso aplicativo pesquisa linhas em um grande banco de dados. Essas linhas existem em vários idiomas e o código antigo selecionou uma linha para cada idioma em uma matriz. Agora, como essas consultas são a parte mais demorada do nosso aplicativo, eu queria fazer apenas uma consulta que grava diretamente em uma matriz.
Os códigos de idioma são 2 códigos ISO-639 (pt para inglês, FR para o francês).
Velho Caminho (este é apenas um código simplificado para mostrar a intenção)
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];
}
Eu gostaria de fazer algo assim:
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);
Mas não sei como devo definir Lancodes.
Funciona com uma lista constante (tempo de compilação) como esta
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');
Mas isso não é útil, pois os idiomas podem variar de caso para caso.
Se eu escrever algo como
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);
Funciona apenas se houver 1 código de idioma na sequência.
Então, minha pergunta é: alguém sabe como fazer isso funcionar? A documentação do Oracle é tão grande que não sei para onde olhar. Eu tentei maneiras diferentes, mas nenhuma funcionou.
EDITAROk, encontrei uma solução que funciona. Não é elegante, não é avançado, mas funciona bem. Coloquei uma lista ou cláusulas na minha consulta e ela retorna o que preciso no formulário que preciso.
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]);
É mais rápido quando há mais de 2 idiomas, então eu chamo essa variante ou a antiga, dependendo do número de idiomas para buscar.
Solução
Provavelmente isso Artigo de Asktom pode ajudá -lo.
Outras dicas
Você não pode fazer isso sem Oracle Dynamic SQL. Você terá que construir sua cláusula no tempo de execução e executar imediato. Pelo menos você pode usar o método 1, com base em suas consultas.
Eu usei uma tabela antes de composta por um ID e um conjunto de linhas, onde as linhas são a permutação dos possíveis valores na lista "In". Então eu me junto à tabela com base no ID e isso me dá os resultados de que preciso.
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' );
...
Tudo o que você precisa fazer é escolher o valor correto "ID" 2, 3, 4 ... e colocá -lo na junção.
... string principal: = 'Selecione * da tabela onde id =: uniqid e idioma em'; - pode se dividir em dois para acompanhar: uniqd ... selecione idioma_code em v_string de x_table; Cópia de loop e concat v_string para lancode_string e com '' ,; loop final; .. Concate Lancode para a string principal. .. Prepare e execute a sequência principal.