Postgresql user-defined type and trigger - postgresql

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$;

Related

Checking Function Parameter Postgres

i'm trying to find the fastest way to check whether my postgres function parameter is null or empty.
my current function looks like:
CREATE OR REPLATE FUNCTON update_seller_detail(seller_id int,
seller_name varchar, seller_address varchar, seller_gender varchar)
RETURNS character varying
LANGUAGE plpsql
SECURITY DEFINER
AS $function$
BEGIN
IF seller_id = '' THEN
RAISE NOTICE 'Check Parameter'
return -1
ELSE
IF seller_name = '' THEN
UPDATE seller SET address=seller_address, gender=seller_gender WHERE id=seller_id;
ELSEIF seller_address = '' THEN
UPDATE seller SET name=seller_name, gender=seller_gender WHERE id=seller_id;
ELSE seller_gender= '' THEN
UPDATE seller SET name=seller_name, address=seller_address WHERE id=seller_id;
END IF;
END IF;
END;
$function$
Is there any way to find which of the parameter is null? so i can set my update to the column that's not null. thanks
you can use coalesce(nullif(trim(<column-reference>), '') in update query with column reference:
CREATE OR REPLACE FUNCTION update_seller_detail(
seller_id int,
seller_name varchar,
seller_address varchar,
seller_gender varchar
)
RETURNS character varying
LANGUAGE plpgsql
SECURITY DEFINER
AS
$function$
BEGIN
IF seller_id ISNULL THEN
RAISE NOTICE 'Check Parameter';
return -1;
ELSE
UPDATE public.seller s
SET name = coalesce(nullif(trim(seller_name), ''), s.name),
address = coalesce(nullif(trim(seller_address), ''), s.address),
gender = coalesce(nullif(trim(seller_gender), ''), s.gender)
WHERE id = seller_id;
return 1;
END IF;
END;
$function$

How to insert value into table from auto-increment value in other table : postgressql (update and insert two table)

I am trying to insert the value "stock_id_artc" int4 into table "tbl_stock" from auto increment inserted value "artc_id" in table "tbl_artc" :
CREATE OR REPLACE FUNCTION "public"."update_artc"("_artc_id" int4, "_artc_name" varchar, "_artc_fourn" int4, "_artc_sector" int4, "_stock_min" int4)
RETURNS "pg_catalog"."void" AS $BODY$
-- Routine body goes here...
DECLARE
BEGIN
UPDATE tbl_artc SET
artc_name = _artc_name,artc_fourn=_artc_fourn,artc_sector=_artc_sector
WHERE artc_id = _artc_id ;
IF NOT FOUND THEN
INSERT INTO tbl_artc(artc_name,artc_fourn,artc_sector)
VALUES
(_artc_name,_artc_fourn,_artc_sector);
END IF;
UPDATE tbl_stock
SET stock_qt_min_alert = _stock_min
WHERE stock_id_artc=_artc_id;
IF NOT FOUND THEN
INSERT INTO tbl_stock(stock_id_artc,stock_qt_artc,stock_qt_min_alert)
VALUES
(artc_id,0,_stock_min);
END IF;
RETURN;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
the solution :
CREATE OR REPLACE FUNCTION "public"."update_artc"("_artc_id" int4, "_artc_name" varchar, "_artc_fourn" int4, "_artc_sector" int4, "_stock_min" int4)
RETURNS "pg_catalog"."void" AS $BODY$
-- Routine body goes here...
DECLARE tableId integer;
BEGIN
UPDATE tbl_artc SET
artc_name = _artc_name,artc_fourn=_artc_fourn,artc_sector=_artc_sector
WHERE artc_id = _artc_id ;
IF NOT FOUND THEN
INSERT INTO tbl_artc (artc_name,artc_fourn,artc_sector) VALUES (_artc_name,_artc_fourn,_artc_sector) RETURNING artc_id INTO tableId;
END IF;
UPDATE tbl_stock
SET stock_qt_min_alert = _stock_min
WHERE stock_id_artc=_artc_id;
IF NOT FOUND THEN
INSERT INTO tbl_stock (stock_id_artc,stock_qt_artc,stock_qt_min_alert) VALUES (tableId,0,_stock_min);
END IF;
RETURN;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100

query has no destination for result data error

I am having the following function in `
CREATE OR REPLACE FUNCTION public.get_avalable_providers(
start_day_id integer,
end_day_id integer,
number_of_days integer,
requested integer)
RETURNS SETOF provider AS
$BODY$declare
required integer;
available_product integer;
p provider;
p_id integer;
noa integer;
begin
FOR p IN SELECT * FROM provider
loop
FOR p_id, noa IN SELECT id, number_of_availables FROM product
WHERE provider_id = p.id
LOOP
required = requested/noa;
select available_product =
public.get_available_products_biggerthan(
start_day_id, end_day_id, number_of_days, required, p_id);
if available_product = number_of_days then
return next p;
exit;
end if;
END LOOP;
end loop;
return;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION public.get_avalable_providers(integer, integer, integer,
integer, integer)
OWNER TO postgres;
The above functions is supposed to return some providers that have sufficient amount of the requested product in a days range
it is taking advantage anther function get_available_products_biggerthan and I am getting the following error:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function
get_avalable_products(integer,integer,integer,integer,integer) line 15 at
SQL statement
Question
where am I making mistake?
https://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW
The result of a SQL command yielding a single row (possibly of
multiple columns) can be assigned to a record variable, row-type
variable, or list of scalar variables. This is done by writing the
base SQL command and adding an INTO clause
try below (I only fixed obvious syntax):
CREATE OR REPLACE FUNCTION public.get_avalable_providers(
start_day_id integer,
end_day_id integer,
number_of_days integer,
requested integer)
RETURNS SETOF provider AS
$BODY$declare
required integer;
available_product integer;
p provider;
p_id integer;
noa integer;
begin
FOR p IN (SELECT * FROM provider)
loop
FOR p_id, noa IN (SELECT id, number_of_availables FROM product
WHERE provider_id = p.id)
LOOP
required = requested/noa;
select public.get_available_products_biggerthan(
start_day_id, end_day_id, number_of_days, required, p_id) INTO available_product ;
if available_product = number_of_days then
return next p;
exit;
end if;
END LOOP;
end loop;
return;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;

PostgreSQL function does not return a value

-- I can not understand where the error
CREATE OR REPLACE FUNCTION get_person_membership (IN person_urn CHARACTER VARYING)
RETURNS TEXT AS
$BODY$
DECLARE
result text;
urn ALIAS FOR $1;
BEGIN
SELECT INTO result pers.mx_groupmember FROM mt_person AS pers, mxt_recordheader AS rech
WHERE rech.primaryurn = 'urn'
AND rech.entitytype = 'person'
AND rech.logicalserverprefix = 'EA'
AND rech.id = pers.id;
RETURN result;
END;
$BODY$
LANGUAGE plpgsql
VOLATILE
COST 100
i simplified your query:
For input you can use $1, this goes to direct your condition.
You can return direct your result if you dont need anywhere else.
select * from get_person_membership('something');
CREATE OR REPLACE FUNCTION get_person_membership (IN person_urn CHARACTER VARYING)
RETURNS TEXT AS
$BODY$
BEGIN
RETURN (select pers.mx_groupmember --returns single value
FROM mt_person AS pers, mxt_recordheader AS rech
WHERE rech.primaryurn = $1 --input value from person_urn
AND rech.entitytype = 'person'
AND rech.logicalserverprefix = 'EA'
AND rech.id = pers.id);
END;
$BODY$
LANGUAGE plpgsql
VOLATILE
COST 100
No need for PL/pgSQL, a simple SQL function will do:
CREATE OR REPLACE FUNCTION get_person_membership (IN person_urn CHARACTER VARYING)
RETURNS TEXT AS
$BODY$
SELECT pers.mx_groupmember
FROM mt_person AS pers
JOIN mxt_recordheader AS rech ON rech.id = pers.id
WHERE rech.primaryurn = person_urn --<< input parameter
AND rech.entitytype = 'person'
AND rech.logicalserverprefix = 'EA';
$BODY$
LANGUAGE sql;

PostgreSQL: How to assign null value to variable within function's parameter list?

I am trying to assign null value to variable within function parameter list using PostgreSQL 9.3 version.
Example: My try
create or replace function fun_para(a varchar(20) =null, dt timestamp =null)
...
ERROR: input parameters after one with a default value must also have defaults
if you have a parameter with a default value all following parameters have to have a default value as well. So this is valid:
create or replace function fun_para(a varchar(20) = null, dt timestamp = null)
returns void
language plpgsql as $$ BEGIN END; $$;
While this is invalid:
create or replace function fun_para(a varchar(20) = null, dt timestamp)
returns void
language plpgsql as $$ BEGIN END; $$;
This again is valid:
create or replace function fun_para(a varchar(20), dt timestamp = null)
returns void
language plpgsql as $$ BEGIN END; $$;
This is valid as well:
create or replace function fun_para(dt timestamp, a varchar(20) = null)
returns void
language plpgsql as $$ BEGIN END; $$;