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

Responder a