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)
-   -   Diferente comportamiento de un query (https://www.clubdelphi.com/foros/showthread.php?t=95658)

Angel.Matilla 19-04-2022 10:57:15

Diferente comportamiento de un query
 
Buenos días. A ver si alguien me puede dar una explicación porque llevo días luchando con ese mensaje y no sé como resolverlo. Estoy ejecutando este query en un BB.DD. FB 2.5.6:
Código SQL [-]
SELECT A.Sigla,
       COALESCE(B.Votos, 0) Votos1,
       (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv AND Proceso = :Proceso1 AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv)) Total1,
       COALESCE(C.Votos, 0) Votos2,
       (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv AND Proceso = :Proceso2 AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv)) Total2, 
       CASE WHEN A.Codigo = -3 THEN 0 WHEN Codigo < 0 THEN A.Codigo ELSE 1 END Orden
  FROM Partidos A
       LEFT JOIN (SELECT Partido, SUM(Votos) Votos FROM Resultados WHERE CodPrv = :PrvIns AND Proceso = :Proceso1 AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = :PrvIns)
                         GROUP BY Partido) B ON B.Partido = A.Codigo
       LEFT JOIN (SELECT Partido, SUM(Votos) Votos FROM Resultados WHERE CodPrv = :PrvIns AND Proceso = :Proceso2 AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = :PrvIns)
                         GROUP BY Partido) C ON C.Partido = A.Codigo
 WHERE A.CodPrv = :PrvIns AND (B.Votos > 0 OR C.Votos > 0)
 ORDER BY Orden DESC, Votos1 DESC, Votos2 DESC, Sigla
Sé que el query es un poco complejo, pero el problema no es ese. El problema es que si lo ejecuto desde la aplicación me da el error SQLCODE -804: Incorrect values within SQLDA structure pero si lo ejecuto desde SQL Manager, con los mismos valores en todos los parámetros en ambos casos, se ejecuta correctamente y me da los resultados que quiero y no entiendo por qué ese diferente comportamiento.

Casimiro Notevi 19-04-2022 11:42:49

¿Podemos ver el código de tu programa donde se asigna esa sentencia y los parámetros?

Angel.Matilla 19-04-2022 12:33:31

Como no, pero es un poco lío.
Código:

cAux = "AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv";
switch (((PTreeMun)MunRes->GetNodeData(MunRes->FocusedNode))->Nivel)
{
    case 2:
          cAux = cAux + " AND Municipio IN (SELECT Codigo FROM Dl01 WHERE CodPrv = A.CodPrv AND CodPar = :Codigo)";
          break;
    case 4:
          cAux = cAux + " AND Municipio = :Codigo";
          break;
}
cAux = cAux + ")";

fMenu->Auxiliar->Close();
fMenu->Auxiliar->SQL->Text = "SELECT A.Sigla,";
fMenu->Auxiliar->SQL->Add("COALESCE(B.Votos, 0) Votos1, (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv AND Proceso = :Proceso1 " + cAux + ") Total1,"
fMenu->Auxiliar->SQL->Add("COALESCE(C.Votos, 0) Votos2, (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv AND Proceso = :Proceso2 " + cAux + ") Total2, CASE WHEN A.Codigo = -3 THEN 0 WHEN Codigo < 0 THEN A.Codigo ELSE 1 END Orden");
fMenu->Auxiliar->SQL->Add("FROM Partidos A LEFT JOIN (SELECT Partido, SUM(Votos) Votos FROM Resultados WHERE CodPrv = :PrvIns AND Proceso = :Proceso1 " + StringReplace(cAux, "A.CodPrv", ":PrvIns", oReplace) + " GROUP BY Partido) B ON B.Partido = A.Codigo");
fMenu->Auxiliar->SQL->Add("LEFT JOIN (SELECT Partido, SUM(Votos) Votos FROM Resultados WHERE CodPrv = :PrvIns AND Proceso = :Proceso2 " + StringReplace(cAux, "A.CodPrv", ":PrvIns", oReplace) + " GROUP BY Partido) C ON C.Partido = A.Codigo");
fMenu->Auxiliar->SQL->Add("WHERE A.CodPrv = :PrvIns AND (B.Votos > 0 OR C.Votos > 0) ORDER BY Orden DESC, Votos1 DESC, Votos2 DESC, Sigla");

lPrueba = false;
for (nItem = 0; nItem < SelRes->Items->Count; nItem ++)
    if (SelRes->Items->Item[nItem]->Checked)
    {
          fMenu->Auxiliar->ParamByName("Proceso1")->AsInteger = StrToInt(SelRes->Items->Item[nItem]->SubItems->Strings[0]);
          fMenu->Auxiliar->ParamByName((lPrueba ? (String)"Proceso2" : (String)"Proceso1"))->AsInteger = StrToInt(SelRes->Items->Item[nItem]->SubItems->Strings[0]);
          lPrueba = !lPrueba;
    }
if (((PTreeMun)MunRes->GetNodeData(MunRes->FocusedNode))->Nivel > 1)
    fMenu->Auxiliar->ParamByName("Codigo")->AsInteger = ((PTreeMun)MunRes->GetNodeData(MunRes->FocusedNode))->Codigo;
fMenu->Auxiliar->ParamByName("PrvIns")->AsString  = ((PTreeMun)MunRes->GetNodeData(MunRes->FocusedNode))->Provincia;
if (((PTreeMun)MunRes->GetNodeData(MunRes->FocusedNode))->Nivel < 4 && StrToIntDef(PadMun->Text, 0) > 0)
    fMenu->Auxiliar->ParamByName("Padron")->AsInteger = StrToIntDef(PadMun->Text, 0);
fMenu->Auxiliar->Open();

  • cAux es un AnsiString
  • SelRes es un TListView
  • Dl01 es una vista de la BB.DD.
En el código que puse al principio supongo que ((PTreeMun)MunRes->GetNodeData(MunRes->FocusedNode))->Nivel vale 1 y por eso no aparece parte del código que se puede montar.

Angel.Matilla 19-04-2022 12:38:42

Ya las tablas que se usan son estas:
Código SQL [-]
CREATE TABLE RESULTADOS (
  CODPRV VARCHAR(3) CHARACTER SET ISO8859_1 DEFAULT '13' NOT NULL COLLATE ES_ES_CI_AI,
  PROCESO INTEGER NOT NULL,
  MESA INTEGER NOT NULL,
  PARTIDO INTEGER DEFAULT 1 NOT NULL,
  VOTOS INTEGER);
Código SQL [-]
CREATE TABLE MESAS (
  CODPRV VARCHAR(3) CHARACTER SET ISO8859_1 DEFAULT '13' NOT NULL COLLATE ES_ES_CI_AI,
  CODIGO INTEGER NOT NULL,
  MUNICIPIO INTEGER DEFAULT 1 NOT NULL,
  DISTRITO SMALLINT NOT NULL,
  SECCION SMALLINT NOT NULL,
  MESA VARCHAR(2) CHARACTER SET ISO8859_1 DEFAULT 'U' NOT NULL COLLATE ES_ES_CI_AI);
Código SQL [-]
CREATE TABLE PARTIDOS (
  CODPRV VARCHAR(3) CHARACTER SET ISO8859_1 DEFAULT '13' NOT NULL COLLATE ES_ES_CI_AI,
  CODIGO SMALLINT NOT NULL,
  NOMBRE VARCHAR(45) CHARACTER SET ISO8859_1 NOT NULL COLLATE ES_ES_CI_AI,
  SIGLA VARCHAR(10) CHARACTER SET ISO8859_1 COLLATE ES_ES_CI_AI,
  ACTIVO SMALLINT DEFAULT 1,
  COLOR INTEGER DEFAULT 0);

Casimiro Notevi 19-04-2022 12:49:46

Pon un "breakpoint" en la línea:
fMenu->Auxiliar->Open();
Y mira con el debug qué valor tiene "SQL".
Puede ser que con las concatenaciones haya código "pegado", algo como: "order byCampoTal" en lugar de "order by CampoTal", por poner un ejemplo.

Angel.Matilla 19-04-2022 12:56:41

Cita:

Empezado por Casimiro Notevi (Mensaje 546559)
Pon un "breakpoint" en la línea:
fMenu->Auxiliar->Open();
Y mira con el debug qué valor tiene "SQL".
Puede ser que con las concatenaciones haya código "pegado", algo como: "order byCampoTal" en lugar de "order by CampoTal", por poner un ejemplo.

No, lo había pensado pero el código que he usado en SQL Manager está copiado en ese punto. Es más: he probado pegando tal cual el código que he usado en SQL Manager en la aplicación y sigue dando el mismo error.

Casimiro Notevi 19-04-2022 13:16:50

Cita:

Empezado por Angel.Matilla (Mensaje 546560)
No, lo había pensado pero el código que he usado en SQL Manager está copiado en ese punto. Es más: he probado pegando tal cual el código que he usado en SQL Manager en la aplicación y sigue dando el mismo error.

Míralo, por si acaso, ya que esos programas sqlmanager, ibexpert, etc. suelen tener controles para evitar esas cosas.

Angel.Matilla 19-04-2022 13:29:01

Gracias. Lo comprobaré.

Casimiro Notevi 19-04-2022 13:33:33

No pierdes nada comprobándolo, aunque resulte que no sea eso finalmente.
Es que una vez me pasaba eso mismo y resultó que era el problema.

Angel.Matilla 19-04-2022 18:03:54

Tienes razón. Ya te diré.

fjcg02 19-04-2022 21:11:44

Tienes algunos parámetros repetidos.

Creo recordar que no se puede repetir el nombre de los parametros porque se grilla el chino.

:Proceso1
:Proceso2
:PrvIns

Cambia los nombres y prueba.

Saludos

Angel.Matilla 20-04-2022 09:57:06

Lo había pensado e hice la prueba, pero sigue dando el mismo error. Lo que me sorprende es que en el SQL Manager funciona perfectamente.

Casimiro Notevi 20-04-2022 10:34:27

A ver si algún parámetro no tiene un valor correcto o algo así.

Angel.Matilla 22-04-2022 10:42:27

Gracias a todos por vuestras respuestas. Al final, y después de días probando, encontré la solución dándole "la vuelta" al query y en vez de la monstruosidad que puse el primer día me ha quedado algo mucho más sencillo y fácil de ejecutar:
Código SQL [-]
SELECT A.Partido, B.Sigla, COALESCE(SUM(A.Votos), 0) Votos, CASE WHEN A.Partido = -3 THEN 0 WHEN A.Partido < 0 THEN A.Partido ELSE 1 END Orden 
  FROM Resultados A 
  LEFT JOIN Partidos B ON A.CodPRv = B.CodPrv AND A.Partido = B.Codigo 
 WHERE A.CodPrv = :PrvIns AND A.Proceso = :Proceso 
   AND A.Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv) AND Votos > 0 GROUP BY A.Partido, B.Sigla


La franja horaria es GMT +2. Ahora son las 04:46:59.

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