Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Query no funciona... ¡A veces! (https://www.clubdelphi.com/foros/showthread.php?t=82231)

Angel.Matilla 12-02-2013 11:32:24

Query no funciona... ¡A veces!
 
En un programa con C++ Builder 5 tengo este query en un base de datos Firebird:
Código SQL [-]
SELECT * FROM Ls01 A, Auxiliar C 
WHERE A.CodPrv = 45 AND A.Situacion IN (0, 1, 2) AND A.Junta = C.Valor AND C.Tipo = 2 
ORDER BY NomJun, Apellidos, Nombre, Referencia
Si lo ejecuto dentro de un programa no me da ningún resultado; sin embargo, si lo pruebo en IBManager EXACTAMENTE con las mismas tablas si me saca filas, que por otra parte es el resultado lógico y por más vueltas que estoy dando no soy capaz de encontrar la razón ¿Alguna idea y/o ayuda? Ls01 es una vista sobre varias tablas y Auxiliar es una tabla sin índices.

Casimiro Notevi 12-02-2013 11:53:29

Que lo estás ejecutando en bases de datos distintas :)

duilioisola 12-02-2013 14:57:45

O te has olvidado de hacer el Open del Query... :)

Muestra el código que utilizas para ejecutar el SQL, que no somos adivinos...

Angel.Matilla 13-02-2013 08:03:44

Perdón; tenéis razón:
Código SQL [-]
Query->Close(); Query->SQL->Add("SELECT * FROM Ls01 A, Auxiliar C 
WHERE A.CodPrv = :CodPrv AND A.Situacion IN (0, 1, 2) AND A.Junta = C.Valor AND C.Tipo = 2
ORDER BY NomJun, Apellidos, Nombre, Referencia");
Query->ParamByName("CodPrv")->AsInteger = nCodPrv;
Query->Open();
Así está puesto en el programa. CodPrv es un entero sin signo y está bien definido (en este caso el valor es 45 porque es el código de Toledo) y Query es un TIBQuery asociado a la base de datos Firebird, lógicamente.

Angel.Matilla 13-02-2013 08:38:15

Explico el proceso completo. Este query lo uso para generar unos listados y la consulta depende de las opciones que elige el usuario, pero la SELECT es la misma en todos los casos. Esa tabla Auxiliar la uso para guardar los valores que se escogen en el formulario (por ejemplo el código de población) y monto esto:
Código:

Query->Close();
Query->SQL->Text = "SELECT * FROM Ls01 A";

qAuxil->Close();
qAuxil->SQL->Text = "SELECT DISTINCT Tipo FROM Auxiliar WHERE Usuario = :Usuario";
qAuxil->ParamByName("Usuario")->AsString = NombreUser;                   
qAuxil->Open();
for (; !qAuxil->Eof; qAuxil->Next())
    Query->SQL->Text = Query->SQL->Text + ", Auxiliar " + CHAR(65 + fPersonas->qAuxil->FieldByName("Tipo")->AsInteger);

Query y qAuxil son sendos TIBQuery y en la tabla Auxiliar sólo se guardan dos tipos: 1 y 2. De esta forma, si hubiera valores de ambos tipos, el query sería por ejemplo:
Código:

SELECT * FROM Ls01 A, Auxiliar B, Auxiliar C
WHERE A.CodPrv= :CodPrv
AND B.Tipo = 1 AND B.Usuario = :Usuario AND A.Profesion = B.Valor
AND C.Tipo = 2 AND C.Usuario = :Usuario AND A.Junta = C.Valor

El programa se ejecuta sin errores; he probado todos los casos para la tabla Auxiliar: sin datos, sólo con un tipo de datos (bien 1 bien 2) y con ambos tipos. En todos los casos el query se monta bien, pero al ejecutarlo es como si la tabla Auxiliar se hubiera vaciado y no es así. En ningún punto del código se hace un DELETE sobre dicha tabla.

Casimiro Notevi 13-02-2013 10:13:42

Creo que no se entiende lo que explicas, Angel.Matilla.
Por lógica, si tienes un select que unas veces trae unos datos y otras veces trae otros datos distintos, tan sólo tienes varias posibilidades:

- que no sea el mismo select
- que sea el mismo select, pero los parámetros sean distintos
- que sea el mismo select, y lo ejecutes en bases de datos distintas

No puede haber más opciones, o sea, no puedes ejecutar un select con unos parámetros en una misma base de datos y que te devuelva datos distintos. Lógicamente.

Deberías detener el programa justo antes de lanzar el query y mirar la sentencia completa en ambos casos, para ver si está formada correctamente.

La otra opción es que nos pases la BD y probemos nosotros :)

Angel.Matilla 13-02-2013 11:48:16

Gracias prola respuesta Casimiro.
Cita:

Empezado por Casimiro Notevi (Mensaje 454947)
Creo que no se entiende lo que explicas, Angel.Matilla.

Lo que he puesto es el código de cómo monto el query.
Cita:

Empezado por Casimiro Notevi (Mensaje 454947)
Por lógica, si tienes un select que unas veces trae unos datos y otras veces trae otros datos distintos, tan sólo tienes varias posibilidades:

- que no sea el mismo select
- que sea el mismo select, pero los parámetros sean distintos
- que sea el mismo select, y lo ejecutes en bases de datos distintas

No puede haber más opciones, o sea, no puedes ejecutar un select con unos parámetros en una misma base de datos y que te devuelva datos distintos. Lógicamente.

Deberías detener el programa justo antes de lanzar el query y mirar la sentencia completa en ambos casos, para ver si está formada correctamente.

Ninguna de las tres opciones que das es correcta: es el mismo select con los mismos parámetros y la misma base de datos. No es que unas veces traiga resultados y otras no, es que dentro del programa no devuelve nada y en IBManager sí. Para comprobarlo paro la ejecución justo antes de hacer el open() y copio el contenido del query para ejecutarlo en IBManager.
Cita:

Empezado por Casimiro Notevi (Mensaje 454947)
La otra opción es que nos pases la BD y probemos nosotros :)

No tengo inconveniente en pasarte el programa (está hecho en Builder 5) y la base de datos; dime como y dónde.

Angel.Matilla 13-02-2013 12:39:37

Añado más cosas. Perdonad que lo haga así, pero según voy haciendo pruebas lo pngo. He probado a montar el código de otra manera.
Ejecuto un bucle para leer los datos de Auxiliar del tipo 1:
AnsiString cAux = "";
Código:

Query->Close();
Query->SQL->Text = "SELECT Valor FROM Auxiliar WHERE Tipo = 1 AND Usuario = :Usuario";
Query->ParamByName("Usuario")->AsString = NombreUser;
Query->Open();
for (; !Query->Eof; Query->Next())
    cAux = cAux + FormatFloat("0', '", Query->FieldByName("Valor")->AsInteger);
cAux = cAux.SubString(1, cAux.LastDelimiter(",") - 1);

Esto la hago para que me quede uan cadena del tipo
Cita:

1, 2, 3, 4
que luego pondré en el query así:
Código:

Query->Close();
Query->SQL->Text = "SELECT * FROM Ls01 WHERE CodPrv = :CodPrv AND Junta IN (" + cAux + ") ORDER BY Apellidos, Nombre";
Query->ParamByName("CodPrv")->AsInteger = nCodPrv;
Query->Open();

¡Y así funciona perferctamente! Lo que pasa que no quisera usar este método porque puede crear verdaderas monstruosidades de código.

Casimiro Notevi 13-02-2013 12:47:40

Hombre, yo aseguraría que el problema, como ya dije antes, es que no creas el mismo select o los mismos parámetros. Es pura lógica.

Angel.Matilla 13-02-2013 16:14:29

Puedo garantizar que es el mismo query (parando la ejecución del prograna JUSTO antes del Open() y copiando el contenido del SQL->Text) y la misma base de datos (no hay otra en Firebird en ese disco).

Casimiro Notevi 13-02-2013 16:23:20

Pero, Ángel, un mismo sql en una misma base de datos, es imposible que devuelva datos distintos.
Por muchas vueltas que quieras darle, no puede ser.

Salvo que la base de datos esté estropeada y se haya vuelta loca.

Casimiro Notevi 13-02-2013 16:24:19

Ya digo, si quieres copia y pega aquí el sql y comprime la BD y la subes también.
Haremos pruebas y compararemos resultados.

Chris 13-02-2013 22:16:37

Y si probás? :P
... A.Situacion IN (0, 1, 2, 3, 4) ...

Saludos!

Al González 14-02-2013 20:37:30

Ángel:

1. ¿Después de hacer el Open, el conjunto de datos permanece abierto (en estado dsBrowse)? Cabe la posibilidad de que algo lo esté cerrando de inmediato y tú lo interpretes como que no trajo nada de la base de datos.

2. ¿Casualmente tiene algo en la propiedad Filter o en el evento OnFilterRecord? Puede que tenga establecido algo que filtre los registros que trajo de la base de datos, de tal forma que no queda ninguno disponible para ser leído.

3. Tal vez tú crees que le estás dando los "mismos" parámetros en tu programa que en IBManager, pero alguno de ellos podría ser diferente por algo que no ves a simple vista, quizá espacios en blanco al final de los campos / valores VarChar / String. Por cierto, ¿no estarás usando campos Char en lugar de VarChar para datos de longitud variable, o alguna opción de "trim" automático que se esté aplicando en un caso y no en el otro?

No dejes de informarnos.

Saludos.

Angel.Matilla 15-02-2013 10:50:29

Cita:

Empezado por Chris (Mensaje 455004)
Y si probás? :P
... A.Situacion IN (0, 1, 2, 3, 4) ...

Saludos!

Asi funciona perfectamente. Tendre que dejarlo con esas sintaxis, aunque no me guste mucho por lo grandes que pueden ser los querys.

Angel.Matilla 15-02-2013 17:09:34

Después de muchas idas y venidas he solucionado el problema; vale que de una forma un poco "pedestre"... pero funciona. Esa tabla Auxiliar yo la uso para guardar datos temporales con lo cual tiene muchos accesos; bueno, pues para solucionar el problema del query inicial que no funcionaba lo que he hecho es simplemente cerrar y abrir la tabla una vez que termino de rellenarla.

He probado de todo: con ApplyUpdates(), poniendo en las tablas y querys CachedUpdates a true y a false, y al final sólo me ha valido cerrar y abrir. Si a alguien se le ocurre otra solución que me lo diga.

Gracias a todos por las ideas.


La franja horaria es GMT +2. Ahora son las 14:19:27.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi