Principales respuestas
AUTO GENERAR CODIGO 001-0000001

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
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.
- 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.
- 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>"; }
- Editado Willams Morales lunes, 2 de noviembre de 2015 17:01
- Propuesto como respuesta Karen MalagónModerator martes, 3 de noviembre de 2015 20:34
- Marcado como respuesta Nill Frank jueves, 5 de noviembre de 2015 21:32
-
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- Propuesto como respuesta Karen MalagónModerator miércoles, 4 de noviembre de 2015 20:30
- Marcado como respuesta Nill Frank jueves, 5 de noviembre de 2015 21:31
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.
-
-
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.
- 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.
- 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>"; }
- Editado Willams Morales lunes, 2 de noviembre de 2015 17:01
- Propuesto como respuesta Karen MalagónModerator martes, 3 de noviembre de 2015 20:34
- Marcado como respuesta Nill Frank jueves, 5 de noviembre de 2015 21:32
-
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
-
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- Propuesto como respuesta Karen MalagónModerator miércoles, 4 de noviembre de 2015 20:30
- Marcado como respuesta Nill Frank jueves, 5 de noviembre de 2015 21:31
-
-
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-0000010Pero 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-0000004Asi 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
-
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 -
Muchas Gracias de Antemano Buen Miguel Egea Gómez
-
-
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 -
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