none
¿Como manejar la numeración en una columna computada? RRS feed

  • Pregunta

  • Hola amigos, he creado la siguiente tabla que tiene un campo computado que lo conforma un id y la fecha de creacion, mi pregunta se basa en como controlar  esta parte : RIGHT('000000000', habria problemas cuando se complete la numeracion? poniendo un escenario por ejemplo:   despues del registro 999999999.

    De antemano muchas gracias. saludos.

    --Tabla
    CREATE TABLE Documento(
    	id_documento INT NOT NULL PRIMARY KEY,
    	fecha DATE NOT NULL,
    	encargado VARCHAR (100) NOT NULL,
        cod_referencia AS 'REF' + cast(datepart(yy,fecha) as varchar(25)) + cast(datepart(mm,fecha) as varchar(25)) + RIGHT('000000000' + CAST(id_documento AS VARCHAR(10)), 9)
    ) 
    GO
    
    --procedimiento almacenado
    CREATE PROCEDURE sp_RegistrarDoc
    (
    	
    	@id_documento  int,
    	@fecha         date,
    	@encargado	   varchar(100)
    		
    )
    AS
    BEGIN
    	BEGIN TRANSACTION
    	BEGIN TRY
    
    	IF (@id_documento IS NOT NULL) AND EXISTS(SELECT * FROM Documento WHERE id_documento=@id_documento) AND @id_docuemnto<>''
    	RAISERROR('El documento ya se encuentra registrado, verificar datos',16,1)
    		
    	INSERT INTO Documento(id_documento,fecha,encargado)
    
    	VALUES(@id_documento,@fecha,@encargado)			
    	SET @id_docuemnto=IDENT_CURRENT('Documento') + 1
    				
    	COMMIT TRANSACTION
    	END TRY
    	BEGIN CATCH
    	IF @@TRANCOUNT>0
    	ROLLBACK TRANSACTION
    	EXEC sp_retornarError
    	END CATCH
    END
    GO
    
    --Ejecutando el sp
    DECLARE @id int 
    Select @id = coalesce(MAX(id_documento),0) + 1 FROM Documento
    execute  sp_RegistrarDoc @id,'06/05/2017','JUAN SANCHEZ RODRIGUEZ'
    select * from Documento
    
    --Resultado consulta
     id_documento   fecha               cod_referencia              encargado
     1                       2017-01-06     REF20175000000001    JUAN SANCHEZ RODRIGUEZ







    • Editado Jose Alrey viernes, 6 de enero de 2017 8:06
    viernes, 6 de enero de 2017 7:59

Respuestas

  • habria problemas cuando se complete la numeracion? poniendo un escenario por ejemplo:   despues del registro 999999999.

    Sí, habrá un problema: Al hacer el RIGHT de la concatenación, se perderá el dígito más significativo, con lo que te saldrá un valor duplicado en ese campo, cosa que seguramente perjudicará la lógica de tu aplicación, incluso aunque el servidor SQL no arroje ningún error dad que no tienes ninguna restricción de unicidad sobre el campo.

    No tiene ningún remedio fácil, salvo el de asegurarse de que el número de dígitos que pones en el campo es sobradamente grande para cualquier posible utilización que se vaya a hacer de esos datos.

    Una buena precaución sería la de agregar un CONSTRAINT en la definición de la tabla sobre el id_documento que verifique que no se excede el valor máximo, así por lo menos si eso ocurre te das cuenta de que se han excedido los parámetros de diseño en lugar de ignorar el problema silenciosamente. Otra alternativa es la de agregar un índice único sobre el campo calculado; esta sería útil si haces búsquedas sobre ese campo, pero a diferencia del constraint consume espacio de almacenamiento en disco.

    viernes, 6 de enero de 2017 8:19
  • Hola

    Estoy de acuerdo con Alberto, también podrías declarar el campo id_documento como bigint (de -2^63 (-9.223.372.036.854.775.808) hasta 2^63-1 (9.223.372.036.854.775.807)) . Con la CONSTRAINT y con los años que te llevaría en "desbordar" el campo puedes estar tranquilo. Claro en el RIGHT('000000000'... tendrías que manejar la cantidad de ceros segun el tamaño en caracteres de id_documento.

    Saludos

    • Marcado como respuesta Jose Alrey sábado, 7 de enero de 2017 22:36
    viernes, 6 de enero de 2017 13:08
  • Jose Alrey,

    Limita el formato que tienes según el rango del tipo de dato que defines, por ejemplo, un tipo int tiene como rango superior '2,147,483,647' (10 dígitos), por tanto no podrás asignar un valor mayor a la columna [id_documento] porque obtendrás un error por desbordamiento aritmético y el problema no será el valor calculado sino el límite del tipo de dato de la columna [id_documento], así que si deseas ir hasta el límite que el tipo de dato permita entonces has que el formato de numeración contenga 10 dígitos y no 9.

    cod_referencia AS CONCAT(
    	   'REF', 
    	   DATEPART(YEAR, fecha), 
    	   DATEPART(MONTH, fecha), 
    	   RIGHT(CONCAT('0000000000', id_documento), 10))
    
    /*FORMAT(id_documento, '0000000000')*/

    Sin embargo, yo nunca he visto que la numeración de algún documento sea tan amplio, tu restringes la misma a la cantidad de dígitos que consideres oportuno como por ejemplo 7 (que creo es la que determina las entidades tributarias) y cuando llegues al limite 9999999 entonces inicias en 1, claro con un nuevo número de serie:

    Anterior: 001-9999999
    Nuevo: 002-0000001



    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    • Marcado como respuesta Jose Alrey sábado, 7 de enero de 2017 22:34
    viernes, 6 de enero de 2017 15:34

Todas las respuestas

  • habria problemas cuando se complete la numeracion? poniendo un escenario por ejemplo:   despues del registro 999999999.

    Sí, habrá un problema: Al hacer el RIGHT de la concatenación, se perderá el dígito más significativo, con lo que te saldrá un valor duplicado en ese campo, cosa que seguramente perjudicará la lógica de tu aplicación, incluso aunque el servidor SQL no arroje ningún error dad que no tienes ninguna restricción de unicidad sobre el campo.

    No tiene ningún remedio fácil, salvo el de asegurarse de que el número de dígitos que pones en el campo es sobradamente grande para cualquier posible utilización que se vaya a hacer de esos datos.

    Una buena precaución sería la de agregar un CONSTRAINT en la definición de la tabla sobre el id_documento que verifique que no se excede el valor máximo, así por lo menos si eso ocurre te das cuenta de que se han excedido los parámetros de diseño en lugar de ignorar el problema silenciosamente. Otra alternativa es la de agregar un índice único sobre el campo calculado; esta sería útil si haces búsquedas sobre ese campo, pero a diferencia del constraint consume espacio de almacenamiento en disco.

    viernes, 6 de enero de 2017 8:19
  • Hola

    Estoy de acuerdo con Alberto, también podrías declarar el campo id_documento como bigint (de -2^63 (-9.223.372.036.854.775.808) hasta 2^63-1 (9.223.372.036.854.775.807)) . Con la CONSTRAINT y con los años que te llevaría en "desbordar" el campo puedes estar tranquilo. Claro en el RIGHT('000000000'... tendrías que manejar la cantidad de ceros segun el tamaño en caracteres de id_documento.

    Saludos

    • Marcado como respuesta Jose Alrey sábado, 7 de enero de 2017 22:36
    viernes, 6 de enero de 2017 13:08
  • Jose Alrey,

    Limita el formato que tienes según el rango del tipo de dato que defines, por ejemplo, un tipo int tiene como rango superior '2,147,483,647' (10 dígitos), por tanto no podrás asignar un valor mayor a la columna [id_documento] porque obtendrás un error por desbordamiento aritmético y el problema no será el valor calculado sino el límite del tipo de dato de la columna [id_documento], así que si deseas ir hasta el límite que el tipo de dato permita entonces has que el formato de numeración contenga 10 dígitos y no 9.

    cod_referencia AS CONCAT(
    	   'REF', 
    	   DATEPART(YEAR, fecha), 
    	   DATEPART(MONTH, fecha), 
    	   RIGHT(CONCAT('0000000000', id_documento), 10))
    
    /*FORMAT(id_documento, '0000000000')*/

    Sin embargo, yo nunca he visto que la numeración de algún documento sea tan amplio, tu restringes la misma a la cantidad de dígitos que consideres oportuno como por ejemplo 7 (que creo es la que determina las entidades tributarias) y cuando llegues al limite 9999999 entonces inicias en 1, claro con un nuevo número de serie:

    Anterior: 001-9999999
    Nuevo: 002-0000001



    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    • Marcado como respuesta Jose Alrey sábado, 7 de enero de 2017 22:34
    viernes, 6 de enero de 2017 15:34
  • Perfecto Williams, cuentas con algun ejemplo a la mano que sea propiamente en sql  para poder reiniciar el consecutivo y la serie  cuando se llegue al limite?.Gracias por tu aporte, saludos.

    domingo, 8 de enero de 2017 3:36