none
Hacer UPDATE y Capturar Valor Actulizado RRS feed

  • Pregunta

  • Saludos, mi inquietud es la siguiente, tengo que crear una funcion que sea capaz de buscar una Secuencia en Varchar y sumarle '1' y devolver esta Secuencia, osea como si fuera un IDENTITY pero por razones del Sistema no puedo usar uno :(, entonces que la funcion devuelva este VARCHAR pero quiero poder altualizar y al mismo tiempo capturar el valor actualizado pero de una pasada

    osea, en una tabla tengo en un campo VARCHAR(10) un 23 entonces quiero al mismo tiempo actualizar a 24 y obtener el valor en una variable para luego devolverla tengo un SP que hace esto pero primero lee, suma 1, actualiza y devuelve

    DECLARE @Secuencia VARCHAR(10) = (SELECT ISNULL(CAST(SECUENCIA AS INT), '0') + CAST('1' AS INT) Secuencia 
    										FROM CAMBIO_CAJA
    									   WHERE OFICINA = @Oficina
    									     AND CAJERO = @Cajero
    									     AND CODIGO = @Caja)
    	
    	UPDATE CAMBIO_CAJA 
    	   SET SECUENCIA = @Secuencia
    	 WHERE OFICINA = @Oficina
    	   AND CAJERO = @Cajero
    	   AND CODIGO = @Caja
    	   
    	   SELECT @Secuencia Secuencia

    Gracias de Antemano


    Luis Y. Ramirez "Recuerda marcar la repuesta como VALIDA si te ha ayudado"

    viernes, 27 de abril de 2012 21:24

Respuestas

  • Estoy de acuerdo con WebJose en que si estás trabajando con un valor que es numérico, que en origen (la tabla) sea ya de un tipo de datos numérico. Ahora bien, en lo que ya no estoy tan de acuerdo es en el hecho de que tengas que bloquear totalmente la tabla para obtener ese nuevo identificador, ya que los problemas de concurrencia que tendrías serían bastante grandes (dependiendo claro está de la carga de tu sistema).

    La forma más normal de hacer lo que necesitas es meterlo todo en un procedimiento almacenado (idealmente fuera de toda transacción si el sistema permite que existan huecos, que es lo que ocurre con IDENTITY) y devolver el valor como parámetro de salida. Algo como:

    CREATE  PROCEDURE dbo.dameSiguienteValor 
    @OFICINA <TIPO DE DATOS>        
    , @CAJERO <TIPO DE DATOS>
    , @CODIGO <TIPO DE DATOS>
    , @siguienteValor INTEGER OUTPUT  
    AS
    	BEGIN     
    		  
    		SET NOCOUNT ON     
    		SET ROWCOUNT 0     
    	
    		SET @siguienteValor = NULL
       
    		UPDATE  dbo.CAMBIO_CAJA  
    		SET     @siguienteValor = SECUENCIA,            
    			SECUENCIA = CAST(SECUENCIA AS INT) + 1    
    		WHERE OFICINA = @Oficina
    		   AND CAJERO = @Cajero
    		   AND CODIGO = @Caja
    	
    	END;
    En cualquier caso, te recomiendo la lectura del muy recomendable artículo "Sequence tables" [http://sqlblog.com/blogs/paul_white/archive/2010/10/19/sequence-tables.aspx] de Paul White

    sábado, 28 de abril de 2012 10:38
  • Hola.

    Te sugiero implementarlo de la siguiente forma:

    http://qwalgrande.blogspot.es/1271102040/obtencion-de-contador-sin-identity/

    Es bastante similar a lo sugerido por Carlos.


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.com
    Sígueme en twitter en http://twitter.com/qwalgrande

    sábado, 28 de abril de 2012 13:26
    Moderador

Todas las respuestas

  • Primero que nada:  ¿Por qué un varchar?  ¿Por qué no un int?  Si son números no veo por qué utilizar un campo tipo varchar.  Eso es no quererse uno mismo porque ese tipo de cosas complica innecesariamente las cosas.

    Segundo:  La solución requeriría de una transacción que bloquee la tabla completa para así asegurar que el valor no se repita.  ¿De verdad quiere eso?  Si aún así lo quiere, entonces sería algo así:

    Declare @valor int;
    
    --Hay que utilizar una transacción.
    Begin Tran;
    
    Select @valor = Cast(Coalesce(secuencia, '0') as int)
    From
        --Table hint para mantener el lock
        Cambio_Caja With (TabLockX, HoldLock)
    Where
        ...
    ;
    
    Set @Valor = @valor + 1;
    
    --Actualizar:
    Update Cambio_Caja
    Set Secuencia = @valor
    Where
        ...
    ;
    
    --Completar la transacción.
    Commit Tran;
    
    NOTA:  No lo probé, pero espero que sirva.  No estoy 100% seguro de la sintaxis de los table hints así que le recomiendo verificarla.

    Jose R. MCP

    viernes, 27 de abril de 2012 22:44
  • Estoy de acuerdo con WebJose en que si estás trabajando con un valor que es numérico, que en origen (la tabla) sea ya de un tipo de datos numérico. Ahora bien, en lo que ya no estoy tan de acuerdo es en el hecho de que tengas que bloquear totalmente la tabla para obtener ese nuevo identificador, ya que los problemas de concurrencia que tendrías serían bastante grandes (dependiendo claro está de la carga de tu sistema).

    La forma más normal de hacer lo que necesitas es meterlo todo en un procedimiento almacenado (idealmente fuera de toda transacción si el sistema permite que existan huecos, que es lo que ocurre con IDENTITY) y devolver el valor como parámetro de salida. Algo como:

    CREATE  PROCEDURE dbo.dameSiguienteValor 
    @OFICINA <TIPO DE DATOS>        
    , @CAJERO <TIPO DE DATOS>
    , @CODIGO <TIPO DE DATOS>
    , @siguienteValor INTEGER OUTPUT  
    AS
    	BEGIN     
    		  
    		SET NOCOUNT ON     
    		SET ROWCOUNT 0     
    	
    		SET @siguienteValor = NULL
       
    		UPDATE  dbo.CAMBIO_CAJA  
    		SET     @siguienteValor = SECUENCIA,            
    			SECUENCIA = CAST(SECUENCIA AS INT) + 1    
    		WHERE OFICINA = @Oficina
    		   AND CAJERO = @Cajero
    		   AND CODIGO = @Caja
    	
    	END;
    En cualquier caso, te recomiendo la lectura del muy recomendable artículo "Sequence tables" [http://sqlblog.com/blogs/paul_white/archive/2010/10/19/sequence-tables.aspx] de Paul White

    sábado, 28 de abril de 2012 10:38
  • Hola.

    Te sugiero implementarlo de la siguiente forma:

    http://qwalgrande.blogspot.es/1271102040/obtencion-de-contador-sin-identity/

    Es bastante similar a lo sugerido por Carlos.


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.com
    Sígueme en twitter en http://twitter.com/qwalgrande

    sábado, 28 de abril de 2012 13:26
    Moderador