Ejemplo de lineas de procedimiento almacenado en PostgreSQL
(desarrollo de Fernando San Martin Woerner)
drop function f_centraliza_factura (integer);

CREATE FUNCTION f_centraliza_factura (integer) RETURNS integer AS '
DECLARE
	cod_documento ALIAS FOR $1;
	registros 		RECORD;
	rdetalle		RECORD;
	rtrans 			RECORD;
	rpagos			RECORD;
	rmoneda			RECORD;
	rmontos			RECORD;
	mdebe			numeric(18,6);
	mhaber			numeric(18,6);
	diferencia		numeric(18,6);
	cod_transaccion	varchar(10);
	ctacble			varchar(20);
	pitemconcepto   integer;
BEGIN

	cod_transaccion := ''007'';
	SELECT INTO rtrans MAX(numdocumento) AS maxdoc
					FROM tmi_cabeceradocumentos
					WHERE codtipotransaccion = cod_transaccion;

	IF rtrans.maxdoc IS NULL THEN
		rtrans.maxdoc := 0;
	END IF;

	DELETE FROM tmi_cabeceradocumentos
	WHERE num_documento = cod_documento
	AND tipo_documento = ''F'';

	SELECT INTO rmoneda cod_moneda
	FROM tmi_moneda;


	FOR registros IN
	SELECT
		  f.fecha_factura
		, f.num_factura
		, cl.rut_cliente
		, cl.dir_particular_cliente
		, cl.nom_cliente
		, round(f.valor_factura * f.valor_uf) as valor_factura
		, cc.num_cuenta_contable_i
		, f.valor_uf
		, td.cod_docto_contable
		, c.cod_contrato
		, c.cod_proyecto
	 FROM
	 	  factura f
	 	, contrato c
	 	, cliente cl
	 	, centro_costo cc
	 	, tipo_documento td
	 WHERE
	 	    f.cod_contrato 	= c.cod_contrato
	 	AND c.rut_cliente 	= cl.rut_cliente
	 	AND c.cod_proyecto 	= cc.cod_proyecto
	 	AND c.cod_etapa 	= cc.cod_etapa
	 	AND f.num_factura 	= cod_documento
	 	AND td.cod_tipo_documento = 1
	LOOP

			rtrans.maxdoc := rtrans.maxdoc + 1;

			INSERT INTO tmi_cabeceradocumentos
			(
				  codtipotransaccion
				, numdocumento
				, codestadodocumento
				, foliodocumento
				, fechadocumento
				, coddoctocontable
				, rutpersona
				, direccionpersona
				, tipopersona
				, nombrespersona
				, escliente
				, esproveedor
				, esempleado
				, estacentralizado
				, tipo_documento
				, num_documento
			)
			values
			(
				cod_transaccion,
				rtrans.maxdoc,
				''N'',
				registros.num_factura,
				registros.fecha_factura,
				registros.cod_docto_contable,
				registros.rut_cliente,
				registros.dir_particular_cliente,
				''N'',
				registros.nom_cliente,
				''S'',
				''S'',
				''N'',
				''N'',
				''F'',
				registros.num_factura
			);
			
			FOR rdetalle IN SELECT 
			codconcepto,
			codtipoimputacion,
			sedistribuye,
			numcuentacontable
			FROM tmi_definiciontransaccion
			WHERE codtipotransaccion = cod_transaccion
			LOOP
				IF rdetalle.codconcepto = 1 THEN
					
					INSERT INTO tmi_detalleconceptos
					(
						  codtipotransaccion   
						, numdocumento         
						, codconcepto          
						, itemconcepto
						, numctacontable       
						, monto
						, glosalineal          
						, codmoneda            
						, paridadmoneda        
						, coddoctocbleref      
						, numdoctoref
						, fechadoctoref        
					)
					VALUES
					(
						cod_transaccion,
						rtrans.maxdoc,
						rdetalle.codconcepto,
						1,
						registros.num_cuenta_contable_i,
						registros.valor_factura,
						''FACTURA '' || registros.num_factura, 
						rmoneda.cod_moneda,
						1,
						registros.cod_docto_contable,
						registros.num_factura,
						registros.fecha_factura
					);
				ELSE
					pitemconcepto := 0;
					FOR rpagos IN SELECT 
						  p.monto_contrato * registros.valor_uf as valor
						, ti.cod_doctocontable
						, tp.num_cuenta_contable_d
					from
						  pago_contrato p
						, tipo_pago_ingreso tpi
						, tipo_ingreso ti
						, tmi_proyecto_tipo_ingreso tp
					where
						p.cod_tipo_pago = tpi.cod_tipo_pago
					and tpi.cod_tipo_ingreso = ti.cod_tipo_ingreso
					and ti.cod_tipo_ingreso = tp.cod_tipo_ingreso
					and tp.cod_proyecto = registros.cod_proyecto
					and p.cod_contrato = registros.cod_contrato
					and ti.cod_tipo_ingreso <= 4
					LOOP
						pitemconcepto := pitemconcepto + 1;
						INSERT INTO tmi_detalleconceptos
						(
							  codtipotransaccion   
							, numdocumento         
							, codconcepto          
							, itemconcepto
							, numctacontable       
							, monto                
							, glosalineal          
							, codmoneda            
							, paridadmoneda        
							, coddoctocbleref      
							, numdoctoref
							, fechadoctoref        
						)
						VALUES
						(
							cod_transaccion,
							rtrans.maxdoc,
							rdetalle.codconcepto,
							pitemconcepto,
							rpagos.num_cuenta_contable_d,
							ROUND(rpagos.valor),
							''FACTURA '' || registros.num_factura, 
							rmoneda.cod_moneda,
							1,
							rpagos.cod_doctocontable,
							registros.num_factura,
							registros.fecha_factura
						);
					END LOOP;
				END IF;
			END LOOP;
	
	
	END LOOP;


	SELECT INTO rmontos SUM(monto) as total
	FROM 	tmi_detalleconceptos
	WHERE 	codconcepto = 1
	AND 	numdocumento = rtrans.maxdoc
	AND	codtipotransaccion = ''007'';

	mdebe := rmontos.total;

	SELECT INTO rmontos SUM(monto) as total
	FROM 	tmi_detalleconceptos
	WHERE 	codconcepto = 2
	AND 	numdocumento = rtrans.maxdoc
	AND	codtipotransaccion = ''007'';

	mhaber := rmontos.total;
	diferencia := abs(mhaber - mdebe);

	RAISE NOTICE ''% -> DEBE y HABER %, %, la diferencia %'', 
rtrans.maxdoc, mdebe, mhaber, diferencia; IF diferencia <> 0 THEN IF mdebe > mhaber THEN RAISE NOTICE ''Debe mayor que el haber, diferencia % '', diferencia; IF diferencia <= 5 THEN SELECT INTO rmontos monto FROM tmi_detalleconceptos WHERE numdocumento = rtrans.maxdoc AND codconcepto = 2 AND itemconcepto = 1 and codtipotransaccion = ''007''; RAISE NOTICE ''Monto: % + %'', rmontos.monto, diferencia; UPDATE tmi_detalleconceptos SET monto = rmontos.monto + diferencia WHERE numdocumento = rtrans.maxdoc AND codconcepto = 2 AND itemconcepto = 1 and codtipotransaccion = ''007''; END IF; ELSE RAISE NOTICE ''Haber mayor que el debe, diferencia % '', diferencia; IF diferencia <= 5 THEN SELECT INTO rmontos monto FROM tmi_detalleconceptos WHERE numdocumento = rtrans.maxdoc AND codconcepto = 2 AND itemconcepto = 1 and codtipotransaccion = ''007''; RAISE NOTICE ''Monto: % - %'', rmontos.monto, diferencia; UPDATE tmi_detalleconceptos SET monto = rmontos.monto - diferencia WHERE numdocumento = rtrans.maxdoc AND codconcepto = 2 AND itemconcepto = 1 and codtipotransaccion = ''007''; END IF; END IF; END IF; PERFORM f_reversa_anticiposcc(cod_documento); RETURN rtrans.maxdoc; END;' LANGUAGE 'plpgsql';