Hola como están espero que me puedan ayudar con una duda que me está rondando la cabeza desde hace ya varios días , bueno vamos al asunto ,tengo estas tablas :
CREATE TABLE "*TGeneradorCodigoVentas*" ( Ultimo_CodVenta CHAR(14) NOT NULL , -- 'DVEN-000000001' PRIMARY KEY (Ultimo_CodVenta) ); CREATE TABLE "*TDoc_Venta*" -- representa los datos de cabecera del documento de venta ( Cod_Venta CHAR(14) NOT NULL, -- 'DVEN-000000001' TipoDocumento CHAR(4) NOT NULL CHECK(TipoDocumento IN ('PROF','BOLE','FACT')), Serie_Documento CHAR(3) NOT NULL,--002 Cod_Documento VARCHAR(7) NOT NULL,-- 0000265 Id_Tienda CHAR(8) NOT NULL Id_Cliente CHAR(13) NOT NULL, Id_Usuario CHAR(8) NOT NULL, Fecha_Venta TIMESTAMP NOT NULL, .....etc PRIMARY KEY (Cod_Venta,TipoDocumento,Serie_Documento,Cod_Documento,Id_Tienda), FOREIGN KEY (Id_Tienda) REFERENCES "TTienda", ..... ); el asunto es que deseo generar los códigos de venta y que no se me dupliquen para otros usuarios ya que en cada tienda existen 8 ventanillas de cobro o cajeros , sin nombrar que la empresa posee varias sucursales con las mismas características(varios cajeros) mi código es : *CREATE OR REPLACE FUNCTION* *Sfu_GenerarNuevoCodigoDctoVenta*() RETURNS TEXT AS $$ DECLARE NuevoCodVenta CHAR(14); ParteNumCodActual INT; BEGIN SELECT (SubString(Ultimo_CodVenta FROM 6 FOR 14) :: INT) INTO ParteNumCodActual FROM "*TGeneradorCodigoVentas*"; --Luego generamos el nuevo código de venta IF ParteNumCodActual IS NULL THEN -- Quiere decir que la tabla esta vacía NuevoCodVenta := 'DVEN-' || LPAD(1::TEXT,9,'0'); ELSE -- La tabla ya contiene datos NuevoCodVenta := 'DVEN-' || LPAD((ParteNumCodActual +1)::TEXT,9,'0'); END IF; RETURN NuevoCodVenta; END $$ LANGUAGE 'plpgsql'; *CREATE OR REPLACE FUNCTION* *Sfu_InsertNuevaVenta* ( ....) RETURNS TEXT AS $$ DECLARE Var_Mensaje TEXT; IN_CodVenta CHAR(14); ..... BEGIN --Obtenemos el siguiente código para el documento de venta *IN_CodVenta * := *Sfu_GenerarNuevoCodigoDctoVenta*(); UPDATE "TGeneradorCodigoVentas" SET Ultimo_CodVenta = IN_CodVenta ; .... --Finalmente Insertamos los Datos de la Venta INSERT INTO "TDoc_Venta" (Cod_Venta, , ,.....) VALUES (*IN_CodVenta*, ,....) ..... Var_Mensaje:='LOS DATOS DE LA VENTA SE GRABARON CORRECTAMENTE' ; RETURN Var_Mensaje; END $$ LANGUAGE 'plpgsql'; *LA DUDA* está en que en el modulo de ventas como puedo garantizar que este código que estoy generando ('DVEN-00000000N') con la función anterior no se repita para otras ventanillas de cobro ,ósea si el cajero 1 está realizando una venta y al *MISMO TIEMPO* otros cajeros de la misma tienda están registrando otras ventas ,que debería hacer para garantizar que el código sea diferente para todos ellos ósea ('DVEN-00000000N' , 'DVEN-00000000(N+1)', para el otro cajero ,'DVEN-000000009(N+2)' para el sigte y así ) Tendría que usar *LOCK TABLE* en algún lugar , tendría que usar * TRANSACCIONES* *SERIALIZABLES* (esperar a que un cajero termine de realizar una venta para recién generar otro código ),o la misma función (* Sfu_InsertNuevaVenta*) por tener una transacción implícita ya es suficiente , o que tipo de bloqueos usa postgresl 9.0 será *READ COMMITTED , o SERIALIZABLE* *vamos muchachos por favor seria chévere que opinen o si desean ayudarme en privado :* *plican...@gmail.com *gracias de antemano he , un saludo desde Perú . Ha y porque cojo los códigos de otra tabla y no hago algo así como : SELECT *MAX* (SubString(Ultimo_CodVenta FROM 6 FOR 14) :: INT) INTO ParteNumCodActual FROM "TGeneradorCodigoVentas" NuevoCodVenta := 'DVEN-' || LPAD((ParteNumCodActual +1)::TEXT,9,'0'); Pues porque la tabla de Ventas crece demasiado rápido con tantas ventas que se hacen por día y hacer un *MAX *es muy costoso