Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   PostgreSQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=42)
-   -   Mostrar conjunto de registros (https://www.clubdelphi.com/foros/showthread.php?t=95792)

dape 19-08-2022 19:25:05

Mostrar conjunto de registros
 
Hola, luego de muchos años vuelvo a programar algo y como resultado de esta inactividad hay muchas cosas que he olvidado y me he esta costando.

Resulta que tengo una función en la que realizo una búsqueda según la cadena ingresada, la muestro a continuación:

Código SQL [-]
CREATE OR REPLACE FUNCTION public.sp_buscar_persona(in bapel character varying, OUT codigo character varying, OUT nombre character varying, 
OUT apelpat character varying, OUT apelmat character varying, OUT dpto character varying)
 RETURNS SETOF record
 LANGUAGE plpgsql
AS $function$
declare reg record;
begin
if (bapel != '') then 
    for reg in select tbl_persona.cod_persona,tbl_persona.appat_persona,tbl_persona.apmat_persona,tbl_persona.nom_persona,  tbl_dpto.nom_dpto
    FROM  tbl_dpto INNER JOIN tbl_persona ON tbl_dpto.id_dpto = tbl_persona.id_dpto where appat_persona like bapel||'%' loop
    codigo:=reg.cod_persona;
    nombre:=reg.nom_persona;
    apelpat:=reg.appat_persona;
    apelmat:=reg.apmat_persona;
    dpto:=reg.nom_dpto;
    return next; end loop; return;      
    if (codigo is null) then 
      codigo = '';
    end if;
  end if
end
$function$
;

luego, en lazarus llamo la función usando un TZStoredProc de ZEOS para mostrarlos en un StringGrid, para lo que uso el siguiente código:

Código Delphi [-]
x:=1
sp_buscar_persona.ParamByName('bapel').AsString:=ed_busqueda.Text;
sp_buscar_persona.Prepare;
sp_buscar_persona.ExecProc;
codigo:=sp_buscar_persona.ParamByName('codigo').Value;
sp_buscar_persona.Active:=true; 
for j := 0 to sp_buscar_persona.RecordCount - 1 do
     if not sp_buscar_persona.EOF then
     Begin
             sg_persona.RowCount:=x+1;
             For i := 0 to sp_buscar_persona.Fields.Count - 1 do
             begin
                     sg_persona.Cells[1,x]:=sp_buscar_persona.ParamByName('codigo').Value;
                     sg_persona.Cells[2,x]:=sp_buscar_persona.ParamByName('nombre').Value;
                     sg_persona.Cells[3,x]:=sp_buscar_persona.ParamByName('apelpat').Value;
                     sg_persona.Cells[4,x]:=sp_buscar_persona.ParamByName('apelmat').Value;
                     sg_persona.Cells[5,x]:=sp_buscar_persona.ParamByName('dpto').Value;
             end;
             inc(x);
             sp_buscar_persona.Next;
     end

Pero en lugar de mostrarme todos los registros que da la función SQL, sólo me muestra un registro y ¡encima lo duplica!, si alguien puede darme una idea para poder mostrar todos los registros que satisfagan la consulta les estaré muy agradecido.

Por cierto, utilizo la mezcla de FOR con el IF THEN porque cuando uso

Código Delphi [-]
while not sp_buscar_persona.EOF do

se cuelga el programita.

Saludos,

David

mamcx 19-08-2022 22:10:02

Tienes un enredo tremendo.

No necesitas un SP para lo que haces (es mejor usar siempre SQL directo cuando se pueda).

El SP tienes mezclado 2 formas de "devolver" datos: Los OUT parameters y el RETURNS SETOF record, usa uno u otro.

La forma de formatear el código del SP no deja muy claro el flujo.

En Delphi esto: sg_persona.RowCount:=x+1; no se hace!

dape 20-08-2022 00:09:27

Gracias por tu respuesta, estuve viendo la documentación de Postgre, y algunos ejemplos en la web, y ahí escriben la función tal cual la he presentado y cuando la ejecuto en el DBeaver, tal cual está escrita, el servidor me devuelve todos los resultados que coinciden con el criterio de búsqueda.

Vuelvo a presentar el código SQL con mejor formato

Código SQL [-]
CREATE OR REPLACE FUNCTION public.sp_buscar_persona(in bapel character varying, OUT codigo character varying, OUT nombre character varying, 
OUT apelpat character varying, OUT apelmat character varying, OUT dpto character varying)
 RETURNS SETOF record
 LANGUAGE plpgsql
AS $function$
declare
          reg record;
begin
        if (bapel != '') then 
             for reg in select tbl_persona.cod_persona,tbl_persona.appat_persona,tbl_persona.apmat_persona,tbl_persona.nom_persona,  tbl_dpto.nom_dpto
             FROM  tbl_dpto INNER JOIN tbl_persona ON tbl_dpto.id_dpto = tbl_persona.id_dpto where appat_persona like bapel||'%' 
             loop
                   codigo:=reg.cod_persona;
                   nombre:=reg.nom_persona;
                   apelpat:=reg.appat_persona;
                   apelmat:=reg.apmat_persona;
                   dpto:=reg.nom_dpto;
                   return next; 
             end loop; 
       return;      
      end if;
end
$function$
;

La línea sg_persona.RowCount:=x+1; me permite aumentar en uno el número de filas del stringgrid para poder mostrar los registros obtenidos, tal vez no sea la mejor forma pero funciona, si conoces una mejor forma sería excelente si la presentas.

Sin embargo, el problema no es ese, talvez en lugar de retornar SETOF deba retornar TABLE, es decir: RETURNS TABLE(col1 datatype, col2 datatype,...); o tal vez algo en el código en Delphi que me está faltando.

Haré una pruebas...

Saludos,

David

mamcx 20-08-2022 00:16:14

Cita:

Empezado por dape (Mensaje 547996)
La línea sg_persona.RowCount:=x+1; me permite aumentar en uno el número de filas del stringgrid para poder mostrar los registros obtenidos, tal vez no sea la mejor forma pero funciona, si conoces una mejor forma sería excelente si la presentas.

Ah!, entendi que ese era el dataset, pero es el grid. Ok, en ese caso seria mas optimo que asignes la cantidad en solo golpe: sg_persona.RowCount:= sp_buscar_persona.RecordCount


Cita:

Empezado por dape (Mensaje 547996)
Sin embargo, el problema no es ese, talvez en lugar de retornar SETOF deba retornar TABLE, es decir: RETURNS TABLE(col1 datatype, col2 datatype,...); o tal vez algo en el código en Delphi que me está faltando.

Siempre es mejor lo mas especifico. El uso de params OUT en postgres es la forma mas vieja de hacerlo, y queda un poco confuso. Es mejor definer un RECORD/TABLE concreto.


La franja horaria es GMT +2. Ahora son las 07:31:41.

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