ERROR: type "exception" does not exist in the PostgreSQL block - plpgsql

CREATE OR REPLACE PROCEDURE addl_field_pkg.del_symm_dopl224_sp ( i_ORDE_NO varchar(30),
i_ACTN_CODE varchar(30), i_CIRC_NO varchar(30), i_ADDL_FIELD text,
i_ADDL_FIELD_ACTN text, i_ADDL_CONTENT text, o_ERR_CODE INOUT bigint, o_ERR_MSG INOUT text ) AS $body$
DECLARE
ORDER_COMPLETED_EX exception;
w_order_no varchar(20);
BEGIN
if ( current_setting('addl_field_pkg.w_completed')::char = milestone_pkg.CHK_IPLC_ORDER_STATUS_F(i_orde_no) ) then
raise ORDER_COMPLETED_EX;
end if;
select orde_no into STRICT w_order_no
from symm_dopl224
where orde_no = i_orde_no
and actn_code = i_actn_code
and circ_no = i_circ_no
and addl_field = i_addl_field
and addl_field_actn = i_addl_field_actn
and addl_content = i_addl_content;
delete from symm_dopl224
where orde_no = i_orde_no
and actn_code = i_actn_code
and circ_no = i_circ_no
and addl_field = i_addl_field
and addl_field_actn = i_addl_field_actn
and addl_content = i_addl_content;
Exception
when no_data_found then
ROLLBACK;
o_err_code := SQLSTATE;
o_err_msg := 'Update failure - Record does not exist';
when others then
ROLLBACK;
o_err_code := SQLSTATE;
o_err_msg := 'System error - '||sqlerrm;
END;
$body$
LANGUAGE PLPGSQL
;

Related

Postgresql user-defined type and trigger

I have user defined type in Postgresql and table with this type:
CREATE TYPE public.hour_integer AS
(
q_1 integer,
q_2 integer,
q_3 integer,
q_4 integer
);
CREATE TABLE IF NOT EXISTS device_hours_data
(
device_hours_data_id serial,
date date,
h01 hour_integer ,
h02 hour_integer ,
h03 hour_integer ,
...
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
Now I need to create a trigger before insert with rule: if h01.q_1 is null then h01.q_1 = 0. How can I use correct syntax please ?
CREATE OR REPLACE FUNCTION public.device_hours_data_trigger()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
v_hour character varying;
BEGIN
IF (NEW).h01.q_1 = null THEN
NEW.h01.q_1 = 0;
END IF;
...
RETURN NEW;
END;
$BODY$;
I am using something like:
NEW.h01.q_1 = 0; - syntax error,
(NEW).h01.q_1 = 0; - syntax error,
(NEW.h01).q_1 = 0; - syntax error....
Could you please help me?
Thanks
The only way I could get it to work is as suggested by #a_horse_with_no_name, something like:
CREATE OR REPLACE FUNCTION public.device_hours_data_trigger()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
v_hour character varying;
new_hour hour_integer;
BEGIN
new_hour = NEW.h01;
IF new_hour.q_1 = null THEN
new_hour.q_1 = 0;
END IF;
...
NEW.h01 = new_hour;
RETURN NEW;
END;
$BODY$;

When exception raised rollingback the insert

I am calling the function
SELECT sbc_schemaA.func1(customernum => '5566789',custlocID => 25)
Whenever there is an exception raised in sbc_schemaD.func5 the insert statemet of sbc_schemaC.func4 is rolledback.
Even exception is raised it should not rollback the into custgartbl.
Please help me.
The code of the function sbc_schemaA.func1 as below.
It is calling another function "sbc_schemaB.func2" inside it.
create or replace function sbc_schemaA.func1(
customernum in VARCHAR default null,
custlocID in NUMERIC default null
) RETURNS void AS
$$
declare
ajsid numeric;
begin
select * from sbc_schemaB.func2(customernum, custlocID) into strict ajsid;
exception
when raise_exception then
RAISE info '%','ErrMsg: ' || substr(sqlerrm,1,instr(sqlerrm,e'\n',1,1)) ;
end $$ language plpgsql;
The code of the function sbc_schemaB.func2 as below.
It is calling another function "sbc_schemaC.func3" inside it.
create or replace function sbc_schemaB.func2(
customernumber IN VARCHAR,
custlocID IN NUMERIC,
brsid out NUMERIC) AS
$$
declare
v_ermsg text;
v_cnx text;
begin
select * from sbc_schemaC.func3(customernumber => customernumber,custlocID => custlocID) into strict brsid;
exception
when raise_exception then
GET STACKED DIAGNOSTICS v_ermsg = MESSAGE_TEXT,
v_cnx = PG_EXCEPTION_CONTEXT;
v_ermsg := set_context(v_ermsg::text, v_cnx::Text);
raise exception e'%', v_ermsg;
end $$ language plpgsql;
The code of the function sbc_schemaC.func3 as below.
It is calling another function "sbc_schemaC.func4" and "sbc_schemaD.func5" inside it.
create or replace function sbc_schemaC.func3(customernumber IN VARCHAR,
custlocID IN NUMERIC,
ajsid out NUMERIC,
brsid out NUMERIC) AS
$$
declare
v_ajsid numeric;
btpID numeric:=0;
select * from sbc_schemaC.func4(p_customernum => customernumber,
p_custlocID => custlocID
) into v_ajsid;
ajsid := v_ajsid;
if v_ajsid = 0 then
begin
select * from sbc_schemaD.func5(customernumber,btpID);
exception
when raise_exception then
GET STACKED DIAGNOSTICS v_ermsg = MESSAGE_TEXT,
v_cnx = PG_EXCEPTION_CONTEXT;
v_ermsg := set_context(v_ermsg::text, v_cnx::Text);
raise exception e'%', v_ermsg;
end;
end if;
end $$ language plpgsql;
The code of the function sbc_schemaC.func4 as below.
CREATE OR REPLACE FUNCTION sbc_schemaC.func4(
p_customernum VARCHAR,
p_custlocID numeric,
p_ajsid OUT numeric
) AS
$$
declare
v_cnx text;
v_ermsg text;
begin
insert into custgartbl(account_num,custlocID) values(p_customernum,p_custlocID);
exception
when raise_exception then
GET STACKED DIAGNOSTICS v_ermsg = MESSAGE_TEXT,
v_cnx = PG_EXCEPTION_CONTEXT;
v_ermsg := set_context(v_ermsg::text, v_cnx::Text);
raise exception e'%', v_ermsg;
end $$ language plpgsql;
The code of the function sbc_schemaD.func5 as below.
CREATE OR REPLACE FUNCTION sbc_schemaD.func5 (customernumber text, btpID numeric) AS $body$
DECLARE
errmsg text;
v_ermsg text;
v_cnx text;
BEGIN
if btpID = 0 then
errmsg := cermssg('error')
raise exception e'%',errmsg;
end if;
exception
when raise_exception then
GET STACKED DIAGNOSTICS
v_ermsg = MESSAGE_TEXT,
v_cnx = PG_EXCEPTION_CONTEXT;
v_ermsg := v_ermsg||E'\n'||v_cnx;
raise exception e'%', v_ermsg;
END;
$body$
LANGUAGE PLPGSQL
Thanks in advance.
The code you post for func3 is buggy; it is missing the initial BEGIN.
Anyway, when simplified, your code looks like this:
SELECT * FROM func4(...) INTO ...;
IF v_ajsid = 0 THEN
BEGIN
SELECT * FROM func5(...);
EXCEPTION
WHEN raise_exception THEN
RAISE EXCEPTION ...;
END;
END IF;
Since you raise an exception in the exception handler, the whole (sub?)transaction in which func3 is executed gets rolled back, so the effects of the call to func4 are undone.
You have to something other than raising an exception in the exception handler if you want to preserve the effects of the call to func4.

Postgres calling Function in functio does not what I expect

Hi,
the function F_B() returns in bracket "(i,m)" instead of 2 columns "i" and "m"!
CREATE FUNCTION F_A
(
i_productionsitename IN TEXT,
i_printjobid IN TEXT,
i_isnewlycreated IN INT,
o_returncode OUT TEXT,
o_message OUT TEXT
) AS $$
DECLARE
BEGIN
Select 'i', 'm' into o_ReturnCode, o_message;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM F_A('DRM', '42',1);
=> i & m
CREATE FUNCTION F_B
(
i_productionsitename IN TEXT,
i_printjobid IN TEXT,
i_isnewlycreated IN INT,
o_returncode OUT TEXT,
o_message OUT TEXT
) AS $$
DECLARE
rec RECORD;
l_ReturnCode TEXT;
l_Message TEXT;
BEGIN
o_ReturnCode := 'l_OK';
o_Message := 'l_Kein Problem';
Select F_A (i_ProductionSiteName, i_PrintJobID , i_isnewlycreated) INTO l_ReturnCode, l_Message ; --rec ;
o_ReturnCode := l_ReturnCode; --' rec.o_message;
o_Message := l_Message;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM F_B('DRM', '42',1);
=> gives (i,m) & null
Why is second column empty, but first has the 2 values?
What is wrong?
Thanks

PostgreSQL 9.5: Return columns based on input parameter

I have the following table.
Table:
CREATE TABLE tblTest
(
Column1 int,
Column2 int,
Column3 int,
Column11 int,
Column111 int,
Column1111 int,
Column22 int,
Column222 int,
Column33 int
);
Records:
INSERT INTO tblTest VALUES(1,2,3,11,111,1111,22,222,33);
I am writting FUNCTION to return the result from above table based on passed parameter.
The parameter p_ColumnName is used to pass the column name. Based on column name the list of columns needs to be display.
Function:
CREATE OR REPLACE FUNCTION ufn_test
(
p_ColumnName text
)
RETURNS -- ? How to specify the dynamic return type or dynamic column list ?
AS
$BODY$
DECLARE v_ColumnsList text;
v_query text;
BEGIN
IF p_ColumnName = 'Column1'
THEN
v_ColumnsList := 'Column11,Column111,Column1111';
ELSIF p_ColumnName = 'Column2'
THEN
v_ColumnsList := 'Column22,Column222';
ELSIF p_ColumnName = 'Column3'
THEN
v_ColumnsList := 'Column33';
END IF;
v_query := 'SELECT '|| v_ColumnsList ||' FROM tblTest';
RETURN QUERY EXECUTE v_query;
END;
$BODY$
LANGUAGE PLPGSQL;
I suggest you are using a type RefCursor in Returns.
Base on the language you are using (SQL, Java ...), you can get data from this Cursor.
So, your function will become to
CREATE OR REPLACE FUNCTION ufn_test( p_ColumnName text )
RETURNS refcursor AS
$BODY$
DECLARE
v_ColumnsList text;
v_query text;
ref_cursor refcursor;
BEGIN
IF (p_ColumnName = 'Column1') THEN
v_ColumnsList := 'Column11,Column111,Column1111';
ELSIF (p_ColumnName = 'Column2') THEN
v_ColumnsList := 'Column22,Column222';
ELSIF (p_ColumnName = 'Column3') THEN
v_ColumnsList := 'Column33';
END IF;
v_query := 'SELECT '|| v_ColumnsList ||' FROM tblTest';
OPEN ref_cursor FOR EXECUTE (v_query);
RETURN ref_cursor;
END;
$BODY$
LANGUAGE plpgsql;
Hopefully it will help you.

Postgresql dynamic sql syntax error

I have a function that accepts an array of table names and loops through the array to create a trigger for each table. The function compiles and is created with no errors.
When I go try to run the function I keep getting the following error and I am not sure what's wrong with my syntax
ERROR:
ERROR: unterminated quoted string at or near "';
ELSE
RAISE EXCEPTION ''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %, %'',TG_OP, TG_LEVEL;
RETURN NULL;
END IF;
INSERT INTO audit.Organization VALUES (audit_row.*);
RETURN null;
END;
"
LINE 53: audit_row.statement_only = 't';
^
USAGE:
SELECT audit.temp_create_trigger(ARRAY['Organization'])
Here's the function:
CREATE OR REPLACE FUNCTION audit.temp_create_trigger(table_names character varying[])
RETURNS character varying AS
$BODY$
DECLARE
table_name varchar;
i int;
BEGIN
FOR i in 1..array_upper(table_names, 1) LOOP
EXECUTE format('CREATE OR REPLACE FUNCTION audit.trigger_function_%1$s() RETURNS TRIGGER AS $$
DECLARE
audit_row audit.%1$s;
include_values boolean;
log_diffs boolean;
h_old hstore;
h_new hstore;
excluded_cols text[] = ARRAY[]::text[];
BEGIN
IF TG_WHEN <> ''AFTER'' THEN
RAISE EXCEPTION ''audit.trigger_function_%1$s may only run as an AFTER trigger'';
END IF;
audit_row = ROW(
nextval(''audit.%1$s_event_id_seq''), -- event_id
TG_TABLE_SCHEMA::text, -- schema_name
TG_TABLE_NAME::text, -- table_name
TG_RELID, -- relation OID for much quicker searches
session_user::text, -- session_user_name
current_timestamp, -- action_tstamp_tx
statement_timestamp(), -- action_tstamp_stm
clock_timestamp(), -- action_tstamp_clk
txid_current(), -- transaction ID
current_setting(''application_name''), -- client application
inet_client_addr(), -- client_addr
inet_client_port(), -- client_port
current_query(), -- top-level query or queries (if multistatement) from client
substring(TG_OP,1,1), -- action
NULL, NULL, -- row_data, changed_fields
''f'' -- statement_only
);
IF NOT TG_ARGV[0]::boolean IS DISTINCT FROM ''f''::boolean THEN
audit_row.client_query = NULL;
END IF;
IF TG_ARGV[1] IS NOT NULL THEN
excluded_cols = TG_ARGV[1]::text[];
END IF;
IF (TG_OP = ''UPDATE'' AND TG_LEVEL = ''ROW'') THEN
audit_row.row_data = hstore(OLD.*) - excluded_cols;
audit_row.changed_fields = (hstore(NEW.*) - audit_row.row_data) - excluded_cols;
IF audit_row.changed_fields = hstore('') THEN
-- All changed fields are ignored. Skip this update.
RETURN NULL;
END IF;
ELSIF (TG_OP = ''DELETE'' AND TG_LEVEL = ''ROW'') THEN
audit_row.row_data = hstore(OLD.*) - excluded_cols;
ELSIF (TG_OP = ''INSERT'' AND TG_LEVEL = ''ROW'') THEN
audit_row.row_data = hstore(NEW.*) - excluded_cols;
ELSIF (TG_LEVEL = ''STATEMENT'' AND TG_OP IN (''INSERT'',''UPDATE'',''DELETE'',''TRUNCATE'')) THEN
audit_row.statement_only = ''t'';
ELSE
RAISE EXCEPTION ''''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'''',TG_OP, TG_LEVEL;
RETURN NULL;
END IF;
INSERT INTO audit.%1$s VALUES (audit_row.*);
RETURN null;
END;
$$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION audit.trigger_function_%1$s()
OWNER TO postgres;', table_names[i]);
EXECUTE format('CREATE TRIGGER audit.%1$s_trigg
BEFORE INSERT OR UPDATE
ON audit.%1$s
FOR EACH ROW
EXECUTE PROCEDURE audit.trigger_function_%1$s();', table_names[i]);
END LOOP;
RETURN 'SUCCESS';
END;
$BODY$
LANGUAGE plpgsql
COST 100;
ALTER FUNCTION audit.temp_create_trigger(character varying[])
OWNER TO postgres;
There are missing and superfluous quotes :
--IF audit_row.changed_fields = hstore('') THEN -- missing quotes
IF audit_row.changed_fields = hstore('''') THEN
.....
--RAISE EXCEPTION ''''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'''',TG_OP, TG_LEVEL; --more quotes then needed
RAISE EXCEPTION ''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'',TG_OP, TG_LEVEL;