Pregunta

Tengo un problema con una consulta Pro*C que estoy intentando optimizar.

Para explicarlo, nuestra aplicación busca filas en una enorme base de datos.Estas filas existen en varios idiomas y el código antiguo seleccionaba una fila para cada idioma en una matriz.Ahora bien, como estas consultas son la parte de nuestra aplicación que consume más tiempo, quería hacer solo una consulta que escriba directamente en una matriz.

Los códigos de idioma son códigos ISO-639 de 2 letras (en para inglés, fr para francés).

Manera antigua (esto es solo un código simplificado para mostrar la intención)

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];
}

Me gustaría hacer algo como esto:

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);

pero no sé cómo debo definir LanCodes.

Funciona con una lista constante (tiempo de compilación) 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');

pero esto no es útil, ya que los idiomas pueden variar de un caso a otro.

Si escribo 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);

solo funciona si hay 1 código de idioma en la cadena.

Entonces mi pregunta es, ¿alguien sabe cómo hacer que esto funcione?La documentación de Oracle es tan grande que no sé dónde buscarla.Probé diferentes formas, pero ninguna funcionó.

EDITAROk, encontré una solución que funciona.No es elegante, no es avanzado pero funciona bien.Puse una lista de cláusulas OR en mi consulta y devuelve lo que necesito en la forma que necesito.

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]);

Es más rápido cuando hay más de 2 idiomas, por lo que llamo a esta variante o a la anterior dependiendo de la cantidad de idiomas a buscar.

¿Fue útil?

Solución

Probablemente este artículo AskTom puede ayudar.

Otros consejos

No se puede hacer esto sin Oracle SQL dinámico . Usted tendrá que construir su cláusula IN en tiempo de ejecución y EXECUTE IMMEDIATE. Al menos se puede utilizar el método 1, sobre la base de sus consultas.

he utilizado una mesa antes de compuesto de un ID y un conjunto de filas en las que las filas son la permutación de los posibles valores de la lista "en". Entonces me uno a la tabla en función de la Identificación y me da los resultados que necesito.

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' );
...

Todo lo que tiene que hacer es elegir a continuación el "ID" correcto valor de 2, 3, 4 ... y colocarla en el unirse.

... Cadena principal: = 'SELECT * FROM tabla WHERE id =: uniqid y de idioma en'; - se puede dividir en dos a acomode: uniqd ... Seleccionar LANGUAGE_CODE en v_string de x_table; lazo  Copiar y de concatenación v_string a LanCode_String y con '',; final del bucle; .. Concat Lancode a la información principal de cadena. .. Preparar y ejecutar la cadena principal.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top