This is one of my  PL/pgsql trigger function.

(makes a cashier shift report)


-- Function: margeimport()

-- DROP FUNCTION margeimport();

CREATE OR REPLACE FUNCTION margeimport()
  RETURNS "trigger" AS
$BODY$
DECLARE 
SQL VARCHAR;
StartRecord INTEGER;
EndRecord INTEGER;
DummyRec Record;
ReportNumber bigint;
ReportExists bool;
f92table VARCHAR;
UpdateSQL VARCHAR;
LastFid INTEGER;
ReportType INTEGER;
DayOfWeek INTEGER;
I INTEGER;
RawData VARCHAR;
LTN INTEGER;
Cashier INTEGER;
RecordSQL VARCHAR;
DataExtractSQL VARCHAR;
MARGERecord RECORD;
LoopCounter INTEGER;
CheckForRecordSQL VARCHAR;
CheckForRecord Record;
LTNList INTEGER[8];
CashierList INTEGER[8];
BEGIN
if (NEW.Fid_24<>'F2009F') or (NEW.fid_24 is null) or (ExtractString(NEW.fid_25, 'F6', '0') <> '99') then 
  RETURN New;
END IF;

f92table:='file_92_'||to_char(NEW.fid_2, 'FMMMyy');

-- Check if the MARGE table is there, otherwise quit

SQL:='SELECT Check_For_Table(''marge'') as test';
FOR DummyRec IN EXECUTE SQL LOOP
	IF DummyRec.test=false THEN
		RAISE NOTICE 'MARGE TABLE DOES NOT EXIST';
		RETURN NEW; 
	END IF;	   
END LOOP;

RAISE NOTICE 'SIGNOFF FOUND';  
EndRecord:=New.Record_number;
SQL:='SELECT Record_Number FROM '||f92table||' where fid_24=''F2009F'' and extractstring(fid_25, ''F6'', ''0'')=''01'' and record_number < '||EndRecord||' and fid_1='||quote_literal(New.Fid_1)||' order by record_number desc limit 1';
FOR DummyRec IN EXECUTE SQL LOOP
   StartRecord:=DummyRec.Record_Number;	
END LOOP;

IF StartRecord IS NULL THEN
	RAISE NOTICE 'STARTRECORD NOT FOUND';
	RETURN NEW;
END IF;

RAISE NOTICE 'StartRecord: % EndRecord: %', StartRecord, EndRecord;

SQL:='CREATE OR REPLACE VIEW MARGEView as select * from '||f92table||' where fid_24=''F2009F'' and fid_1='||quote_literal(New.Fid_1)||' and record_number between '||quote_literal(StartRecord)||' and '||quote_literal(EndRecord); 
EXECUTE SQL;


-- Check if it looks like we have a actuall full report, if not exit

IF (EndRecord-StartRecord) < 30 THEN 
	RAISE NOTICE 'REPORT TO SMALL';
	RETURN NEW; 
END IF;

IF (EndRecord-StartRecord) > 100 THEN 
	RAISE NOTICE 'REPORT TO LARGE';
	RETURN NEW; 
END IF;


-- Now we have the start and end record
-- The unique identifier in the MARGE table will be "Report Number", which is the Date + time, For Example 2312061459. This needs to be an int64
-- First create the unique identifier then go look and see if it is already in the MARGE table

SQL:='SELECT to_char(fid_2, ''ddmmyy'')||to_char(fid_1, ''HH24MISS'') as ReportNo, ExtractString(fid_25, ''F4'', ''0'') as ReportType, To_Char(fid_2, ''D'') as DayOfWeek, fid_25 from MARGEView where record_number='||quote_literal(StartRecord);
FOR DummyRec IN EXECUTE SQL LOOP 
   ReportNumber:=DummyRec.ReportNo;
   ReportType:=DummyRec.ReportType;
   RawData:=DummyRec.Fid_25; -- Used to find out how many LTNs are in the report
   -- Secom has Monday being Day 1 of the week but PostGreSQL has Sunday being day 1, so we need to adjust 
   -- We need to adjust the day by additionally because the report prints after 23:59. 
   -- NOTE: NUMBERS COULD GET SCREWED UP IF SOMEONE MANUALLY PRINTS A REVENUE BY DAY REPORT
   I:=DummyRec.DayOfWeek;
   
   IF I=1 THEN -- "NOW" IS Sunday, NEED TO SUBTRACT 2
	DayOfWeek:=6; 
        ELSEIF  I=2 THEN -- "NOW IS MONDAY, NEED TO SUBTRACT 2"
   	DayOfWeek:=7;
        ELSE DayOfWeek:=I - 2; -- just subtract 2
   END IF;
END LOOP;
RAISE NOTICE 'Report %', ReportNumber;

-- Now we have the unique report number, next step is checking if the report is already in the table. If it is, we update it, if not we add it

ReportExists:=false;
SQL:='SELECT ReportNumber from MARGE where ReportNumber='||quote_literal(ReportNumber);
FOR DummyRec IN EXECUTE SQL LOOP 
  ReportExists:=true;
END LOOP;

LTN:=-1;
-- Check if report has multiple columns (Rev Today by LTN) and if so we need to create more than one record and insert the LTN number in fid_2
IF ReportType=1 THEN
	RAISE NOTICE 'LTN REVENUE BY DAY REPORT FOUND';
	FOR i IN 1..7 LOOP -- LOOP THREW D1 THREW D7 AND LOOK FOR LTN NUMBER
		SQL:='SELECT ExtractString('||quote_literal(RawData)||', '||quote_literal('D'||i)||', ''0'') as ltn';
		FOR DummyRec in EXECUTE SQL LOOP
			LTN:=DummyRec.LTN;
			EXIT WHEN LTN=0;
			LTNList[i]:=LTN; -- this contains a list of the LTNs, needed later when we put the data in 
			CheckForRecordSQL:='SELECT ReportNumber from MARGE where ReportNumber = '||quote_literal(ReportNumber)||' and fid_2= '||quote_literal(LTN); 
			ReportExists:=false;
			FOR CheckForRecord in EXECUTE CheckForRecordSQL LOOP	
				RAISE NOTICE '3 % %', ReportNumber, LTN;
				ReportExists:=true;
			END LOOP;
			IF ReportExists=false THEN
				SQL:='INSERT INTO MARGE(ReportNumber, fid_2) SELECT '||quote_literal(ReportNumber)||','||quote_literal(LTN);
				EXECUTE SQL;
			END IF;
			ReportExists:=true; --this is here just so that the standard report checker-wecker guy does not add any new records
		END LOOP;
	END LOOP;
END IF;

Cashier=-1;
IF ReportType=10 THEN --Revenue Emp By Day
	RAISE NOTICE 'DAILY REVENUE BY EMPLOYEE REPORT FOUND';
	FOR i IN 1..7 LOOP -- LOOP THREW D1 THREW D7 AND LOOK FOR CASHIER CARD NUMBER
		SQL:='SELECT ExtractString('||quote_literal(RawData)||', '||quote_literal('D'||i)||', ''0'') as Cashier';  
		FOR DummyRec in EXECUTE SQL LOOP
			Cashier:=DummyRec.Cashier;  
			EXIT WHEN Cashier=0;
			CashierList[i]:=Cashier; -- this contains a list of the Cashier Numbers, needed later when we put the data in 
			CheckForRecordSQL:='SELECT ReportNumber from MARGE where ReportNumber = '||quote_literal(ReportNumber)||' and fid_3= '||quote_literal(Cashier); 
			ReportExists:=false;
			FOR CheckForRecord in EXECUTE CheckForRecordSQL LOOP	
				RAISE NOTICE '3 % %', ReportNumber, Cashier;
				ReportExists:=true;
			END LOOP;
			IF ReportExists=false THEN
				SQL:='INSERT INTO MARGE(ReportNumber, fid_3) SELECT '||quote_literal(ReportNumber)||','||quote_literal(Cashier);
				EXECUTE SQL;
			END IF;
			ReportExists:=true; --this is here just so that the standard report checker-wecker guy does not add any new records
		END LOOP;
	END LOOP;
END IF;


-- If report is not there then create it
IF ReportExists = false THEN
SQL:='INSERT INTO MARGE(ReportNumber) SELECT '||quote_literal(ReportNumber);
EXECUTE SQL;
END IF;


-- First we want to insert the report TYPE, date and time into MARGE
SQL:='SELECT Extractint(fid_25, ''F4'', ''0'') as ReportType, fid_1, fid_2 from MARGEView WHERE Record_Number='||quote_literal(StartRecord);
FOR DummyRec IN EXECUTE SQL LOOP 
	UpdateSQL:='UPDATE MARGE SET TIME='||quote_literal(DummyRec.fid_1)||', DATE='||quote_literal(DummyRec.fid_2)||', ReportType='||quote_literal(DummyRec.ReportType)||' WHERE ReportNumber='||quote_literal(ReportNumber);
	EXECUTE UpdateSQL;
END LOOP;

-- Now we have the report number in table MARGE, its time to extact the report data itself

RecordSQL:='SELECT ReportNumber, fid_2 from MARGE where ReportNumber='||quote_literal(ReportNumber); -- this will pick up all the records in that report (could be multiple LTNs)

LoopCounter:=0;
FOR MARGERecord IN EXECUTE RecordSQL LOOP -- This loops for every new (Gateway) MARGE record we have (Could be multiple as in the case of LTN Today)
	LoopCounter:=LoopCounter+1;	
  	IF ReportType=1 THEN -- Daily revenue by LTN
      		DataExtractSQL:='SELECT Extractint(fid_25, ''F6'', ''0'') as DataType, FindBaseMARGEFid(Extractint(fid_25, ''F7'', ''0'')) as fid, Extractint(fid_25, ''F8'', ''0'') as valbucketnumber, Cast(ExtractString(fid_25, '||quote_literal('E'||LoopCounter)||', ''0'') as float) as dollars, Extractint(fid_25, '||quote_literal('D'||LoopCounter)||', ''0'') as numbers from MARGEView';

  	ELSIF ReportType=4 THEN -- Revenue by Day 
      		DataExtractSQL:='SELECT Extractint(fid_25, ''F6'', ''0'') as DataType, FindBaseMARGEFid(Extractint(fid_25, ''F7'', ''0'')) as fid, Extractint(fid_25, ''F8'', ''0'') as valbucketnumber, Cast(ExtractString(fid_25, '||quote_literal('E'||DayOfWeek)||', ''0'') as float) as dollars, Extractint(fid_25, '||quote_literal('D'||DayOfWeek)||', ''0'') as numbers from MARGEView';
  
  	ELSIF ReportType=21 THEN -- This works for Shift Report by LTN
      		DataExtractSQL:='SELECT Extractint(fid_25, ''F6'', ''0'') as DataType, FindBaseMARGEFid(Extractint(fid_25, ''F7'', ''0'')) as fid, Extractint(fid_25, ''F8'', ''0'') as valbucketnumber, Cast(ExtractString(fid_25, ''E1'', ''0'') as float) as dollars, Extractint(fid_25, ''D1'', ''0'') as numbers from MARGEView';
  
  	ELSIF ReportType=10 THEN -- This works for Daily Revenue by Emp
      		DataExtractSQL:='SELECT Extractint(fid_25, ''F6'', ''0'') as DataType, FindBaseMARGEFid(Extractint(fid_25, ''F7'', ''0'')) as fid, Extractint(fid_25, ''F8'', ''0'') as valbucketnumber, Cast(ExtractString(fid_25, '||quote_literal('E'||LoopCounter)||', ''0'') as float) as dollars, Extractint(fid_25, '||quote_literal('D'||LoopCounter)||', ''0'') as numbers from MARGEView';

  	ELSE 
 		RETURN NEW; -- Report Not Supported
  	END IF;
	UpdateSQL:='';

	FOR DummyRec IN EXECUTE DataExtractSQL LOOP  -- loop threw and extract the data. This Loops once for each file_92 row
		IF DummyRec.DataType=3 THEN -- regular fids
			IF DummyRec.fid=Lastfid THEN
				RAISE NOTICE 'DUPLICATE FIDS FOUND ABORTING';
				RETURN NEW;
			END IF;
			UpdateSQL:=UpdateSQL||'fid_'||DummyRec.fid||'=';
			-- if numbers are zero then grab the data from "Dollars" instead
			IF DummyRec.Numbers=0 THEN 
				UpdateSQL:=UpdateSQL||DummyRec.dollars||',';
				ELSE 						
				UpdateSQL:=UpdateSQL||DummyRec.Numbers||',';
			END IF;
			LastFid:=DummyRec.fid;
		END IF;

		IF DummyRec.DataType=4 THEN -- Val counts
			UpdateSQL:=UpdateSQL||'fid_'||DummyRec.valbucketnumber+128||'='||DummyRec.Numbers||',';
		END IF;

		IF DummyRec.DataType=5 THEN -- Bucket counts
			UpdateSQL:=UpdateSQL||'fid_'||DummyRec.valbucketnumber*2+255||'='||DummyRec.Numbers||',';
			UpdateSQL:=UpdateSQL||'fid_'||DummyRec.valbucketnumber*2+256||'='||DummyRec.Dollars||',';   
		END IF;

	END LOOP;

	IF length(UpdateSQL) < 3 THEN
		RETURN NEW;
	END IF;

	-- Strip out last comma
	SQL:='SELECT substring('||Quote_Literal(UpdateSQL)||', 1, length('||Quote_Literal(UpdateSQL)||')-1) as UpdateSQL';
	FOR DummyRec IN EXECUTE SQL LOOP 
		UpdateSQL:=DummyRec.UpdateSQL;
	END LOOP;

	RAISE NOTICE 'Report%', ReportNumber;
	SQL:='UPDATE MARGE SET '||UpdateSQL||' WHERE ReportNumber='||ReportNumber;
	
	IF LTN <> -1 THEN -- Are we doing multiple LTNs ? 
		SQL:=SQL||' AND fid_2='||quote_literal(LTNList[LoopCounter]);  -- if so add LTN in there as well
	END IF;

	IF Cashier <> -1 THEN -- Are we doing multiple Cashiers ? 
		SQL:=SQL||' AND fid_3='||quote_literal(CashierList[LoopCounter]);  -- if so add Cashier Number in there as well
	END IF;

	RAISE NOTICE 'COMPLETE UPDATE SQL: %', SQL; 
	IF length(SQL) > 5 THEN  -- otherwise we get Null-SQL execution problems
		EXECUTE SQL;
	END IF;
END LOOP;
RETURN NEW;
END; 
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION margeimport() OWNER TO secom;
