none
AUTO GENERAR CODIGO 001-0000001 RRS feed

  • Pregunta

  • Buenos Días Primero Que Nada Gracias MI Consulta es la Siguiente:

    Estoy Tratando de generar un código en sql server para guardar mi numero de facturas en peru. y tengo la siguiente estructura de mi tabla 

    CREATE TABLE [dbo].[Control] (
        [Codigo] CHAR(20)  NOT NULL,
        [CDoc]   CHAR(20)  NOT NULL,
        [Ser]    INT       NOT NULL,
        [Cor]    INT       NOT NULL,
        [Ing]    DATETIME  DEFAULT (getdate()) NULL,
        [Sta]    CHAR (10) NULL,
        PRIMARY KEY CLEmTERED ([Codigo] ASC)

    Al Querer Guardar Mi Numero de factura yo necesito guardar el numero del documento con el formato

     [Ser]    INT

    es el campo donde voy a grabar mi serie que tendria este formato 001

    [Cor]    INT       NOT NULL,

    es el campo donde almaceno mi correlativo que tendria el siguiente formato 0000001

    para luego hacer uno solo y de esa manera obtener 001-0000001 que seria el numero emitido del documento en caso de que el correlativo llegue a 9999999 la serie se cambiara a 002 y nuevamente el correlativo empezara en 0000001 y asi sucesivamente por lo que deberia quedar

    0001-0000001

    0001-0000002

    0001-0000003

    0001-9999999

    ......................

    0002-0000001

    0002-0000002

    0002-0000003

    0001-9999999

     y bueno asi sucesivamente generarlo gracias te antemano si pudieran ayudarme a hacer la consulta para obtener el codigo espero su respuesta gracias de todo

    sábado, 31 de octubre de 2015 18:44

Respuestas

  • Hola Nill Frank,

    No entiendo donde estás teniendo problemas. A ver, intentaré explicar cuál es el flujo que debería seguir este proceso.

    1. Al cargar el formulario de facturación deberás obtener el número del documento que entiendo lo obtienes de la tabla [Control]. Aquí el formato de los ceros a la izquierda lo debería realizar la aplicación. Considera que el número capturado no necesariamente es el almacenado, por un tema de concurrencia otro usuario podría haber tomado el mismo y haber realizado la transacción. Para esto es necesario que antes de materializar la inserción vuelvas a validar que el número a registrar está disponible. 
    2. Una vez la transacción se haya realizado con éxito deberás incrementar el valor del número en 1 y creo que aquí no hay mayor problema. El tema del número de serie - reitero - no debería ser automatizado, el número de serie se cambia por un tema de decisión de la empresa o limite tributario, recuerda además que la misma empresa podría trabajar con más de un número de serie a la vez.

    En caso persistas en automatizar el cambio de serie deberías hacer lo siguiente:

    string consultaSql = string.Empty;
    if (numeroActual = "9999999")
    {
           consultaSql = "UPDATE Control SET Ser = SerieActual + 1, Cor = 1 WHERE <Condicion>";
    }
    else
    {
           consultaSql = "UPDATE Control SET Cor = numeroActual + 1 WHERE <Condicion>";
    }


    lunes, 2 de noviembre de 2015 17:01
  • si miras lo que dijo ahí jesus lopez, veras que tiene mucha razón.

    Te propongo este método que es lo que yo creo que es eficiente cubriendo tus requisitos.

    CREATE TABLE [dbo].[Control] (
        
        [CDoc]   CHAR(20)  NOT NULL,
        [Ser]    INT       NOT NULL,
        [Cor]    INT       NOT NULL,
        [Ing]    DATETIME  DEFAULT (getdate()) NULL,
        [Sta]    CHAR (10) NULL,
    	CODIGO AS RIGHT('0000'+CAST(SER AS VARCHAR),4)+'-'+RIGHT('000000000'+CAST(COR AS VARCHAR),10)
        PRIMARY KEY CLUSTERED (SER,COR )
    	)
    GO
    
    cvreate procedure dbo.NextValue @ser int,@codigo varchar(15) output
    as
    begin
    set nocount on
      declare @cor int
      if (select count(*) from dbo.Control where ser=@ser)=0
      begin
          insert into dbo.Control select '',@ser,0,getdate(),''
    	  set @cor=1
       end
      update dbo.Control set @cor=cor=cor+1,ing=getdate() where ser=@ser
      select @codigo=codigo from dbo.Control where ser=@ser -- lo hago en 2 pasos porque el update no esta completo y se queda uno antes
        
     return @cor;
    end
    
    go
    declare @ser int,@cor int,@codigo varchar(15)
    set @ser=4
    exec @cor=dbo.NextValue @ser,@codigo output
    select @cor,@codigo
    

    si haces inserciones pues llamar al procedimiento dentro de transacción y eso te generará un bloqueo que impedirá que tanto inserts como updates se ejecuten en paralelo.


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    miércoles, 4 de noviembre de 2015 18:02
    Moderador

Todas las respuestas

  • Hola Nill Frank,

    El formato que esperas mostrar no podrás persistirlo en las columnas que mencionas porque son de tipo numérico y el cero a la izquierda no es considerado. Lo que tendrías que hacer es crear una columna adicional (columna calculada) que implemente el formato que esperas, algo como:

    ALTER TABLE dbo.Control ADD Numero AS RIGHT('000' + CONVERT(varchar(20), Ser), 3) + '-' + RIGHT('0000000' + CONVERT(varchar(20), Cor), 7) PERSISTED;

    Por otro lado, el procedimiento para incrementar en uno el valor de la columna [Cor] es cuando hayas asegurado que la transacción se realizó con éxito, considera además los temas de concurrencia que podría suceder cuando dos o mas usuarios a la vez toman un número de documento.

    Finalmente, no es valido que automatices el correlativo de la serie en base a un número limite. El número de serie puede cambiar en función de varias circunstancias y no necesariamente cuando haya llegado a un "limite". Lo que deberías hacer es tener una columna que defina el límite de número de impresión final o folio en factura electrónica, algo como [UltimoNumero] que determinará hasta que número de documento puede ser facturado.

    domingo, 1 de noviembre de 2015 18:45
  • Gracias Willams Morales lo que deseo es actualizar el campo a 1 u luego agregarle los ceros a la izquierda o algo parecido de Todas Maneras Gracias Por la Ayuda
    lunes, 2 de noviembre de 2015 14:42
  • Hola Nill Frank,

    No entiendo donde estás teniendo problemas. A ver, intentaré explicar cuál es el flujo que debería seguir este proceso.

    1. Al cargar el formulario de facturación deberás obtener el número del documento que entiendo lo obtienes de la tabla [Control]. Aquí el formato de los ceros a la izquierda lo debería realizar la aplicación. Considera que el número capturado no necesariamente es el almacenado, por un tema de concurrencia otro usuario podría haber tomado el mismo y haber realizado la transacción. Para esto es necesario que antes de materializar la inserción vuelvas a validar que el número a registrar está disponible. 
    2. Una vez la transacción se haya realizado con éxito deberás incrementar el valor del número en 1 y creo que aquí no hay mayor problema. El tema del número de serie - reitero - no debería ser automatizado, el número de serie se cambia por un tema de decisión de la empresa o limite tributario, recuerda además que la misma empresa podría trabajar con más de un número de serie a la vez.

    En caso persistas en automatizar el cambio de serie deberías hacer lo siguiente:

    string consultaSql = string.Empty;
    if (numeroActual = "9999999")
    {
           consultaSql = "UPDATE Control SET Ser = SerieActual + 1, Cor = 1 WHERE <Condicion>";
    }
    else
    {
           consultaSql = "UPDATE Control SET Cor = numeroActual + 1 WHERE <Condicion>";
    }


    lunes, 2 de noviembre de 2015 17:01
  • Me baso en este ejemplo  https://social.msdn.microsoft.com/Forums/es-ES/2ad2d4d2-6f35-48f9-87aa-ac75effcc667/autogenerar-cdigo-001000012014?forum=sqlserveres para qure armar el numero de factura por otro lado es el hecho de que tengo que agregarle un campo mas a la tabal para poder guardar el valor que armo de  los 2 campo anteriores
    • Marcado como respuesta Nill Frank jueves, 5 de noviembre de 2015 21:32
    • Desmarcado como respuesta Nill Frank jueves, 5 de noviembre de 2015 21:32
    martes, 3 de noviembre de 2015 0:10
  • si miras lo que dijo ahí jesus lopez, veras que tiene mucha razón.

    Te propongo este método que es lo que yo creo que es eficiente cubriendo tus requisitos.

    CREATE TABLE [dbo].[Control] (
        
        [CDoc]   CHAR(20)  NOT NULL,
        [Ser]    INT       NOT NULL,
        [Cor]    INT       NOT NULL,
        [Ing]    DATETIME  DEFAULT (getdate()) NULL,
        [Sta]    CHAR (10) NULL,
    	CODIGO AS RIGHT('0000'+CAST(SER AS VARCHAR),4)+'-'+RIGHT('000000000'+CAST(COR AS VARCHAR),10)
        PRIMARY KEY CLUSTERED (SER,COR )
    	)
    GO
    
    cvreate procedure dbo.NextValue @ser int,@codigo varchar(15) output
    as
    begin
    set nocount on
      declare @cor int
      if (select count(*) from dbo.Control where ser=@ser)=0
      begin
          insert into dbo.Control select '',@ser,0,getdate(),''
    	  set @cor=1
       end
      update dbo.Control set @cor=cor=cor+1,ing=getdate() where ser=@ser
      select @codigo=codigo from dbo.Control where ser=@ser -- lo hago en 2 pasos porque el update no esta completo y se queda uno antes
        
     return @cor;
    end
    
    go
    declare @ser int,@cor int,@codigo varchar(15)
    set @ser=4
    exec @cor=dbo.NextValue @ser,@codigo output
    select @cor,@codigo
    

    si haces inserciones pues llamar al procedimiento dentro de transacción y eso te generará un bloqueo que impedirá que tanto inserts como updates se ejecuten en paralelo.


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    miércoles, 4 de noviembre de 2015 18:02
    Moderador
  • Gracias A USteds Muchas Gracias y Miles Exitos Karen Malagón y Willams Morales
    jueves, 5 de noviembre de 2015 21:34
  • Por Cierto Olvide Agradecerle de Antemano Por El Gran Aporte que Me Dio Buen Miguel Egea Gómez, Lo Modifique Y Ahora Lo Tengo Asi

    IF OBJECT_ID('NextValue')IS NOT NULL
    	BEGIN 
    	DROP PROC NextValue
    	END
    GO
    create procedure dbo.NextValue @cor int,@codigo varchar(12) output
    as
    begin
    set nocount on
      declare @Ser int
      if (select count(*) from dbo.Control where Cor=@cor)=0
      begin
      	  set @Ser=1
          insert into dbo.Control select '',@ser,0,getdate(),'EMITIDO'
       end
      update dbo.Control set @cor=cor=cor+1,ing=getdate() where ser=@ser
      select @codigo=Emision from dbo.Control where ser=@ser 
     return @cor;
    end
    go
    
    
    declare @ser int,@cor int,@codigo varchar(15)
    select @ser=count(*)
    from Control
    set @ser=@ser+1
    exec @cor=dbo.NextValue @ser,@codigo output;
    select*from control

    Y Bueno Me genera Bien Quedando de la Siguiente Manera:

    1 1 2015-11-12 10:14:48.167 EMITIDO   0001-0000001
    1 2 2015-11-12 10:14:48.167 EMITIDO   0001-0000002
    1 3 2015-11-12 10:14:48.167 EMITIDO   0001-0000003
    1 4 2015-11-12 10:14:48.167 EMITIDO   0001-0000004
    1 5 2015-11-12 10:14:48.167 EMITIDO   0001-0000005
    1 6 2015-11-12 10:14:48.167 EMITIDO   0001-0000006
    1 7 2015-11-12 10:14:48.167 EMITIDO   0001-0000007
    1 8 2015-11-12 10:14:48.167 EMITIDO   0001-0000008
    1 9 2015-11-12 10:14:48.167 EMITIDO   0001-0000009
    1 10 2015-11-12 10:14:48.167 EMITIDO   0001-0000010

    Pero Observando Cada Vez Que Ejecuto el Procedimiento Actualiza la Fecha para Cada Nuevo Registro Tomando Asi El Valor getdate() Para Todas filas de Columna Ing, Lo que Necesito es que En Lugar de ese Campo se Actualice Necesito que mantenga la fecha y hora con la cual se Inserta. Ademas si No Fuera Excesivo Pedir Ya Mas Ayuda Aun Podrias Ayudarme a que cuando el Campo Cor Llegue al :

    1 9999999 2015-11-12 10:14:48.167 EMITIDO 0001-9999999

    Mi Proxima Generacion Sea La Siguiente Por no Decirlo sin Eliminar los Registros Anterios, Actualizar el campo ser ah :0002 y empezar el Campo Cor en :0000001 Y En Conclucion Quedando de la Siguiente Manera:

    1 9999999 2015-11-12 10:14:48.167 EMITIDO   0001-9999999
    2 1 2015-11-12 10:14:48.167 EMITIDO   0001-0000001
    2 2 2015-11-12 10:14:48.167 EMITIDO   0001-0000002
    2 3 2015-11-12 10:14:48.167 EMITIDO   0001-0000003
    2 4 2015-11-12 10:14:48.167 EMITIDO   0001-0000004

    Asi Sucesivamente, Intente Hacerlo Podiendo un IF al Cod Pero No Me Funciono En Si No Se Donde Ponerle el If Para Hacer Dicha Evaluacion O Como Tendria que Manejar esa Parte. De Antemano ya, Muchas Gracias y Espero Puedan Ayudarme, Sin que Mis Preguntas Puedan ser Una Molestia Para Ustedes Gracias. 


    • Editado Nill Frank jueves, 12 de noviembre de 2015 15:33
    jueves, 12 de noviembre de 2015 15:09
  • No te preocupes Nill, para eso estamos! Un abrazo

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    jueves, 12 de noviembre de 2015 15:30
    Moderador
  • Muchas Gracias de Antemano Buen Miguel Egea Gómez
    jueves, 12 de noviembre de 2015 15:38
  • sr. Miguel Egea Gómez Ayudeme con Mi COnsulta Por Favor Si No Fuese una Mis Molestias. Por Favor
    lunes, 16 de noviembre de 2015 22:05
  • Que consulta? que necesitas? porque no abres otro hilo?

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    miércoles, 18 de noviembre de 2015 8:19
    Moderador
  • Como Hacer que no Se Actualice el campo ing. por es getdate() ademas que cuando el cor llegue a 9999999 la serie se actualice al 0002 quedando así ya 0002-0000001  bueno asi cada que el cor llegue a 9999999 el campo ser se actualice en +1, Si Pudiera Ayudarme Por Favor
    • Editado Nill Frank miércoles, 18 de noviembre de 2015 20:42
    miércoles, 18 de noviembre de 2015 15:13