Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   MS SQL Server (https://www.clubdelphi.com/foros/forumdisplay.php?f=23)
-   -   Problema con Cursor en SQL Server 2008 (https://www.clubdelphi.com/foros/showthread.php?t=83055)

Jere_84 07-05-2013 15:27:58

Problema con Cursor en SQL Server 2008
 
Hola Club Delphi, hice un SP en donde dentro creo un cursor y recorro los registros tomados por el select realizando distintos tipos de operaciones. Intento devolver un conjunto de resultados, digamos que por cada registro que recorro, intento mostrar un total y algunos otros datos como el Codigo, Nombre, Ciudad del empleado en este caso.

Código SQL [-]
CREATE PROCEDURE [dbo].[pSJFondoDesemCursor]
(
    @DMesAño DATE,
    @HMesAño DATE, 
    @DCodigSucur VARCHAR(10),
    @HCodigSucur VARCHAR(10),
    @DDenomSucur VARCHAR(60),
    @HDenomSucur VARCHAR(60),
    @DDenomUsuar VARCHAR(40),
    @HDenomUsuar VARCHAR(40), 
    @DCodigCiuda VARCHAR(10),
    @HCodigCiuda VARCHAR(10),
    @DDenomCiuda VARCHAR(60),
    @HDenomCiuda VARCHAR(60),
    @DCodigProvi VARCHAR(10),
    @HCodigProvi VARCHAR(10),
    @DDenomProvi VARCHAR(60),
    @HDenomProvi VARCHAR(60),
    @DCodigEmple VARCHAR(10),
    @HCodigEmple VARCHAR(10),
    @DDenomEmple VARCHAR(60),
    @HDenomEmple VARCHAR(60),
    @Activ CHAR(1),
    @DCuil VARCHAR(13),
    @HCuil VARCHAR(13), 

    
    @CodigEmple VARCHAR(10) OUTPUT,       
    @DescrEmple VARCHAR(60) OUTPUT,        
    @CuilEmple VARCHAR(13) OUTPUT,         
    @CuentaFondoDesem VARCHAR(12) OUTPUT,  
    @LibreFondoDesem VARCHAR(10) OUTPUT,   
    @Calle VARCHAR(60) OUTPUT,             
    @Numer VARCHAR(5) OUTPUT,
    @CodigCiuda VARCHAR (10) OUTPUT, 
    @DescrCiuda VARCHAR(60) OUTPUT,  
    @Porce DECIMAL(15,4) OUTPUT, 
    @ImporFinal DECIMAL(15,4) OUTPUT
       
)
AS
BEGIN
    SET NOCOUNT ON;
 
    DECLARE cFondoDesem CURSOR FOR 
    SELECT tSJDetalLiqui.CodigEmple, tSJEmple.DescrEmple, 
       tSJEmple.Cuil, tSJTotalLiqui.CodigCiuda, 
       tSJTotalLiqui.CodigCateg, tSJTotalLiqui.CodigSecci, 
       tSJTotalLiqui.CodigCargo, tSJTotalLiqui.CodigSucur, 
       tSJTotalLiqui.CodigObraSocia, tSJTotalLiqui.CodigSindi, 
       tSJTotalLiqui.CodigBanco, tSJTotalLiqui.CodigBancoFondoDesem, 
       tSJTotalLiqui.CodigCentrCosto       
  FROM tSJDetalLiqui 
    INNER JOIN tSJTotalLiqui ON tSJDetalLiqui.NumerLiqui = tSJTotalLiqui.NumerLiqui 
           AND tSJDetalLiqui.FechaLiqui = tSJTotalLiqui.FechaLiqui 
           AND tSJDetalLiqui.NumerRecib = tSJTotalLiqui.NumerRecib 
           AND tSJDetalLiqui.CodigEmple = tSJTotalLiqui.CodigEmple 
  INNER JOIN tSJEmple ON tSJTotalLiqui.CodigEmple = tSJEmple.CodigEmple 
  INNER JOIN tKiCiuda ON tSJEmple.CodigCiudaEmple = tKiCiuda.CodigCiuda
  INNER JOIN tKiProvi ON tKiCiuda.CodigProvi = tKiProvi.CodigProvi
  INNER JOIN tSJCateg ON tSJTotalLiqui.CodigCateg = tSJCateg.CodigCateg 
  INNER JOIN tSJSecci ON tSJTotalLiqui.CodigSecci = tSJSecci.CodigSecci 
  INNER JOIN tSJCargo ON tSJTotalLiqui.CodigCargo = tSJCargo.CodigCargo 
  INNER JOIN tKiSucur ON tSJTotalLiqui.CodigSucur = tKiSucur.CodigSucur 
  INNER JOIN tSJObraSocia ON tSJTotalLiqui.CodigObraSocia = tSJObraSocia.CodigObraSocia
  INNER JOIN tSJSindi ON tSJTotalLiqui.CodigSindi = tSJSindi.CodigSindi 
  INNER JOIN tKiBanco ON tSJTotalLiqui.CodigBanco = tKiBanco.CodigBanco 
  INNER JOIN tKiBanco BancoFondoDesem ON tSJTotalLiqui.CodigBancoFondoDesem = BancoFondoDesem.CodigBanco
  INNER JOIN tKiCentrCosto ON tSJEmple.CodigCentrCosto = tKiCentrCosto.CodigCentrCosto
    WHERE MONTH(tSJTotalLiqui.FechaLiqui) BETWEEN MONTH(@DMesAño) AND MONTH(@HMesAño)
    AND YEAR(tSJTotalLiqui.FechaLiqui) BETWEEN YEAR(@DMesAño) AND YEAR(@HMesAño)  
    AND tSJTotalLiqui.CodigSucur BETWEEN @DCodigSucur AND @HCodigSucur
    AND tKISucur.DescrSucur BETWEEN @DDenomSucur AND @HDenomSucur
    AND tSJTotalLiqui.NombrUsuar BETWEEN @DDenomUsuar AND @HDenomUsuar
    AND tSJTotalLiqui.CodigCiuda BETWEEN @DCodigCiuda AND @HCodigCiuda
    AND tKiCiuda.DescrCiuda BETWEEN @DDenomCiuda AND @HDenomCiuda
    AND tKiCiuda.CodigProvi BETWEEN @DCodigProvi AND @HCodigProvi
    AND tKiProvi.DescrProvi BETWEEN @DDenomProvi AND @HDenomProvi
    AND tSJEmple.CodigEmple BETWEEN @DCodigEmple AND @HCodigEmple
    AND tSJEmple.DescrEmple BETWEEN @DDenomEmple AND @HDenomEmple
    AND ((@Activ = 'ACT' and tSJTotalLiqui.FechaEgres IS NULL) OR (@Activ = 'INA' and tSJTotalLiqui.FechaEgres IS NOT NULL) OR (@Activ = 'T')) 
    AND tSJEmple.Cuil BETWEEN @DCuil AND @HCuil
    GROUP BY tSJDetalLiqui.CodigEmple, tSJEmple.DescrEmple, 
           tSJEmple.Cuil, tSJTotalLiqui.CodigCiuda, 
           tSJTotalLiqui.CodigCateg, tSJTotalLiqui.CodigSecci, 
           tSJTotalLiqui.CodigCargo, tSJTotalLiqui.CodigSucur, 
           tSJTotalLiqui.CodigObraSocia, tSJTotalLiqui.CodigSindi, 
           tSJTotalLiqui.CodigBanco, tSJTotalLiqui.CodigBancoFondoDesem, 
           tSJTotalLiqui.CodigCentrCosto  
    
  DECLARE @vCodigEmple VARCHAR(10);
  DECLARE @vDenomEmple VARCHAR(60);     
  DECLARE @vCuil VARCHAR(13);
  DECLARE @vCodigCateg VARCHAR(10);
  DECLARE @vCodigSecci VARCHAR(10);
  DECLARE @vCodigCargo VARCHAR(10);
  DECLARE @vCodigSucur VARCHAR(10);    
  DECLARE @vCodigObraSocia VARCHAR(10);  
  DECLARE @vCodigSindi VARCHAR(10);  
  DECLARE @vCodigBanco VARCHAR(10);  
  DECLARE @vCodigBancoFondoDesem VARCHAR(10);    
  DECLARE @vCodigCentrCosto VARCHAR(10);  
  
    OPEN cFondoDesem
    FETCH NEXT FROM cFondoDesem INTO @vCodigEmple, @vDenomEmple, 
                      @vCuil, @CodigCiuda, 
                   @vCodigCateg, @vCodigSecci, 
                   @vCodigCargo, @vCodigSucur, 
                   @vCodigObraSocia, @vCodigSindi, 
                   @vCodigBanco, @vCodigBancoFondoDesem, 
                   @vCodigCentrCosto   
    
  DECLARE @vNumerLiqui INT;
  DECLARE @vFormaPagoFondoDesem CHAR(1);  
  DECLARE @vFechaEgres DATE;
  DECLARE @vFechaIngre DATE;  
  DECLARE @vFechaIngreEntre DATE;
  DECLARE @vAntig INT;
  DECLARE @vNumerIeric VARCHAR(10);
    DECLARE @vImporFinalPosiv DECIMAL(15,4); 
    DECLARE @vImporFinalNegat DECIMAL(15,4);   

    WHILE @@FETCH_STATUS = 0
    BEGIN
      SET @vFechaEgres = (SELECT FechaEgres
      FROM tSJEmple
    WHERE MONTH(FechaEgres) BETWEEN MONTH(@DMesAño) AND MONTH(@HMesAño)
    AND YEAR(FechaEgres) BETWEEN YEAR(@DMesAño) AND YEAR(@HMesAño)
    AND CodigEmple = @vCodigEmple)
    
    SET @vFormaPagoFondoDesem = (SELECT FormaPagoFondoDesem FROM tKiParam)
    
    IF (@vFechaEgres IS NOT NULL) AND (@vFormaPagoFondoDesem = 'R')
      RETURN;
     
    SELECT @vFechaEgres = FechaEgres,
           @vFechaIngre = FechaIngre
    FROM tSJEmple 
    WHERE CodigEmple = @vCodigEmple
 
    SET @vAntig = DATEDIFF(YEAR, @vFechaIngre, @HMesAño) 
  
    IF (@vAntig >= 1) 
    BEGIN
        SELECT @Porce = tKiParam.PorceFondoDesem2
      FROM tKiParam     
    END
    
    IF (@vAntig <= 1) 
    BEGIN
        SELECT @Porce = tKiParam.PorceFondoDesem1 
      FROM tKiParam     
    END
      
     SELECT @vNumerLiqui = MAX(NumerLiqui),
            @CuentaFondoDesem = tSJTotalLiqui.CuentFondoDesem, 
         @LibreFondoDesem = tSJTotalLiqui.LibreFondoDesem, 
         @Calle = tSJTotalLiqui.Calle, 
         @Numer = tSJTotalLiqui.Numer, 
         @CodigCiuda = tSJTotalLiqui.CodigCiuda, 
         @DescrCiuda = DescrCiuda
    FROM tSJTotalLiqui
    INNER JOIN  tKiCiuda ON tSJTotalLiqui.CodigCiuda = tKiCiuda.CodigCiuda    
    WHERE MONTH(FechaLiqui) BETWEEN MONTH(@DMesAño) AND MONTH(@HMesAño)
    AND YEAR(FechaLiqui) BETWEEN YEAR(@DMesAño) AND YEAR(@HMesAño)
    AND tSJTotalLiqui.CodigEmple = @vCodigEmple
    AND (tSJTotalLiqui.CuentFondoDesem <> '')  
    GROUP BY tSJTotalLiqui.CodigEmple,
             tSJTotalLiqui.CuentFondoDesem, 
             tSJTotalLiqui.LibreFondoDesem, 
             tSJTotalLiqui.Calle, 
             tSJTotalLiqui.Numer, 
             tSJTotalLiqui.CodigCiuda, 
             DescrCiuda

    SELECT @vFechaIngreEntre = FechaIngre
    FROM tSJEmple
    WHERE MONTH(FechaIngre) BETWEEN MONTH(@DMesAño) AND MONTH(@HMesAño)
    AND YEAR(FechaIngre) BETWEEN YEAR(@DMesAño) AND YEAR(@HMesAño)
    AND CodigEmple = @vCodigEmple 
    
    IF (@vFechaIngreEntre IS NULL) 
    BEGIN
      SELECT @vImporFinalPosiv = SUM(ImporFinal)
    FROM tSJDetalLiqui
    WHERE FondoDesem = 'True'
    AND ((TipoConce <> 'PUE') OR (TipoConce <> 'CON'))
    AND Signo = '+'
    AND MONTH(FechaLiqui) BETWEEN MONTH(@DMesAño) AND MONTH(@HMesAño)
    AND YEAR(FechaLiqui) BETWEEN YEAR(@DMesAño) AND YEAR(@HMesAño)
    AND CodigEmple = @vCodigEmple
      
    SELECT @vImporFinalNegat = SUM(ImporFinal)
    FROM tSJDetalLiqui
    WHERE FondoDesem = 'True'
    AND ((TipoConce <> 'PUE') OR (TipoConce <> 'CON'))
    AND Signo = '-'
    AND MONTH(FechaLiqui) BETWEEN MONTH(@DMesAño) AND MONTH(@HMesAño)
    AND YEAR(FechaLiqui) BETWEEN YEAR(@DMesAño) AND YEAR(@HMesAño)
    AND CodigEmple = @vCodigEmple  
    END
    
    IF (@vFechaIngreEntre IS NOT NULL) 
    BEGIN
      SELECT @vImporFinalPosiv = SUM(ImporFinal)
    FROM tSJDetalLiqui
    WHERE FondoDesem = 'True'
    AND ((TipoConce <> 'PUE') OR (TipoConce <> 'CON'))
    AND Signo = '+'
    AND MONTH(FechaLiqui) BETWEEN MONTH(@vFechaIngreEntre) AND MONTH(@HMesAño)
    AND YEAR(FechaLiqui) BETWEEN YEAR(@vFechaIngreEntre) AND YEAR(@HMesAño)
    AND CodigEmple = @vCodigEmple
      
    SELECT @vImporFinalNegat = SUM(ImporFinal)
    FROM tSJDetalLiqui
    WHERE FondoDesem = 'True'
    AND ((TipoConce <> 'PUE') OR (TipoConce <> 'CON'))
    AND Signo = '-'
    AND MONTH(FechaLiqui) BETWEEN MONTH(@vFechaIngreEntre) AND MONTH(@HMesAño)
    AND YEAR(FechaLiqui) BETWEEN YEAR(@vFechaIngreEntre) AND YEAR(@HMesAño)
    AND CodigEmple = @vCodigEmple  
    END
    
    SET @CodigEmple = @vCodigEmple;
    SET @DescrEmple = @vDenomEmple;  
    SET @CuilEmple = @vCuil;
    SET @ImporFinal = @vImporFinalPosiv - @vImporFinalNegat;  
    IF (@ImporFinal IS NULL)
      SET @ImporFinal = 0;
    
    PRINT @CodigEmple
    PRINT @DescrEmple
    PRINT @CuilEmple
    PRINT @CuentaFondoDesem 
    PRINT @LibreFondoDesem 
    PRINT @Calle 
    PRINT @Numer 
    PRINT @CodigCiuda 
    PRINT @DescrCiuda 
    PRINT @Porce 
    PRINT @ImporFinal 
    
    FETCH NEXT FROM cFondoDesem INTO @vCodigEmple, @vDenomEmple, 
                                     @vCuil, @CodigCiuda,
                                       @vCodigCateg, @vCodigSecci, 
                                       @vCodigCargo, @vCodigSucur, 
                                       @vCodigObraSocia, @vCodigSindi, 
                                       @vCodigBanco, @vCodigBancoFondoDesem, 
                                       @vCodigCentrCosto   
    END

  -- Cierre del cursor

  CLOSE cFondoDesem

  -- Liberar los recursos

  DEALLOCATE cFondoDesem   
END

Al ejecutarlo desde el Management Studio de SQL Server veo que solo me muestra como resultado el ultimo registro por que el paso. Digamos si recorrió 5 empleados me muestra los datos del ultimo. y en una solapa de mensajes me muestra los valores de cada uno de lo empleados esto es por el PRINT. El inconveniente de esto no termina aca, en mi aplicación cuando pongo un TSQLStoredProc me carga los parametros pero al hacer un OPEN me aparece Error: SQLStoredProc: Cursor not returned from Query. Traducido al castellano seria: El cursor no regresa consulta. Interpeta digamos que el cursor solo devuelve un solo resultado y tengo que utilizar el comando ExecProc es como si el PRINT en realidad no retornana resultado solo muetra mensajes y no es interpretado por DELPHI como un conjunto de resultados. Intente cambiar el PRINT por el RETURN pero al hacer esto sale en la primera vuelta del bucle devolviendo los datos del Empleado ubicado en la 1º posición. Alguien sabe en que le estoy errando? Eh buscado informacion en distinto sitios y nada... Yo no se si mi error esta en el cursor o es que tengo que utilizarlo de otra manera desde DELPHI.

No se también como tratar el tema de que este SP tiene parámetros de salida, digamos no se si se crean antes de la ejecucion o solo devuelven valor luego de ejecutarse pero este es otro tema.

Utilizo DBExpress, DELPHI 2010.

Gracias.

luisgutierrezb 07-05-2013 16:30:33

Tienes razón, el print no te regresa un resultado, es mas bien con fines de depuración... lo que hago, es hacer una tabla temporal, vaciar los resultados y al final regresar la tabla...

Saludos!

Al González 07-05-2013 16:33:52

Es mejor usar TSQLQuery que TSQLStoredProc cuando vas a obtener un cursor (TSQLStoredProc es para ejecutar un SP que no devuelve resultados o que los devuelve como simples parámetros de salida, no como filas).

Por otra parte, recuerda que los conjuntos de datos DBX (TSQLXXX) son unidireccionales y mientras no hagas "Next", no traerá la siguiente fila (lo normal es acompañarlos con TClientDataSet). ;)

Jere_84 07-05-2013 16:53:15

Cita:

Empezado por Al González (Mensaje 459930)
Es mejor usar TSQLQuery que TSQLStoredProc cuando vas a obtener un cursor (TSQLStoredProc es para ejecutar un SP que no devuelve resultados o que los devuelve como simples parámetros de salida, no como filas).

Por otra parte, recuerda que los conjuntos de datos DBX (TSQLXXX) son unidireccionales y mientras no hagas "Next", no traerá la siguiente fila (lo normal es acompañarlos con TClientDataSet). ;)

Intente usar el TSQLQuery, tenes algún ejemplo de como usarlo?
Si pero no hay Campos persistentes para hacer NEXT y sale error.

Al González 07-05-2013 17:14:58

Cita:

Empezado por Jere_84 (Mensaje 459931)
Intente usar el TSQLQuery, tenes algún ejemplo de como usarlo?

Como cualquier tipo de query, haces una simple consulta sobre el SP:
Código SQL [-]
Select * From MiSP (:Parametro1, :Par2, :Par3, ...)

Cita:

Empezado por Jere_84 (Mensaje 459931)
Si pero no hay Campos persistentes para hacer NEXT y sale error.

¿Qué error aparece en tu pantalla? Me tendrás que perdonar, pues mi vista es mala y desde aquí no logro ver más allá del canal de Panamá. :o

Por otro lado, no entiendo la relación que haces entre campos persistentes y llamar al método Next de un conjunto de datos, ¿podrías explicarlo?

Saludos. :)

Jere_84 07-05-2013 17:36:26

Cita:

Empezado por Al González (Mensaje 459934)
Como cualquier tipo de query, haces una simple consulta sobre el SP:
Código SQL [-]
Select * From MiSP (:Parametro1, :Par2, :Par3, ...)


¿Qué error aparece en tu pantalla? Me tendrás que perdonar, pues mi vista es mala y desde aquí no logro ver más allá del canal de Panamá. :o

Por otro lado, no entiendo la relación que haces entre campos persistentes y llamar al método Next de un conjunto de datos, ¿podrías explicarlo?

Saludos. :)

Cuando hago en un TSQLQuery: Select * From pSJFondoDesem( :Param, :Param1 ....

Al hacer active = true me muestra

El nombre de objeto 'pSJFondoDesemCursor' no es válido.

Como que no es valido llamar un SP de esta manera, porque lo que busca la consulta es una Tabla, capaz que en otras BD funcione pero en SQL Server creo que no por lo visto.

Probe con el ClientDataSet si intento hacer un OPEN me aparece:

TDBXError with message 'Remote error: SQLStoredProc: Cursor not returned from Query'.

Al usar ClientDataSet.Execute, no da error pero solo devuelve dos parámetros con valores de los 11 y tambien los deveulve para el ultimo registro, si intento hacer algo como esto:

Código Delphi [-]
    vdSJInforFondoDesem.ClientDataSetInforNoved.Execute;

    with vdSJInforFondoDesem do
    begin
      ClientDataSetInforNoved.Open;
      ClientDataSetInforNoved.First;
      while not ClientDataSetInforNoved.Eof do
      begin
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@CodigEmple').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@DescrEmple').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@CuilEmple').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@CuentFondoDesem').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@LibreFondoDesem').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@Calle').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@Numer').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@CodigCiuda').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@DescrCiuda').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@Porce').AsString);
        ShowMessage(ClientDataSetInforNoved.Params.ParamByName('@ImporFinal').AsString);
        ClientDataSetInforNoved.Next;
      end;
    end;

Me da el sig error en el OPEN:

TDBXError with message 'Remote error: Could not convert variant of type (OleStr) into type (Date)'.

Voy a buscar mas acerca de esto error quizás sea solucionable y pueda funcionar. :cool:


La franja horaria es GMT +2. Ahora son las 11:17:57.

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