PL/pgSQL
Declaring Variables
DO
$$
DECLARE
mynum integer := 89;
first_name varchar(20) := 'Uday';
hire_date date := '2020-01-01';
start_time timestamp := NOW();
emptyvar integer;
BEGIN
RAISE NOTICE 'My variable % % % % %',
mynum, first_name, hire_date,
start_time, emptyvar ;
END;
$$
Parameters to Function
CREATE OR REPLACE FUNCTION function_name
(INT, INT) RETURNS INT as
$$
DECLARE
x alias for $1;
y alias for $2;
BEGIN
--
END;
$$
Assigning value from result into variable
DO
$$
DECLARE
product_title products.product_name%TYPE;
BEGIN
SELECT product_name FROM products
INTO product_title
where product_id = 1 limit 1;
RAISE NOTICE 'Your product name is %', product_title;
END;
$$
Function Parameter w/t IN and OUT
CREATE OR REPLACE FUNCTION fn_sum_using_inout
( IN x integer, IN y integer, OUT Z integer ) as
$$
BEGIN
z := x+y;
END;
$$
LANGUAGE PLPGSQL;
select fn_sum_using_inout(2,3);
-- another example
CREATE OR REPLACE FUNCTION fn_sum_using_inouts
( IN x integer, IN y integer, OUT Z integer, OUT w integer ) as
$$
BEGIN
z := x+y;
w := x*y;
END;
$$
LANGUAGE PLPGSQL;
select * from fn_sum_using_inouts(2,3);
Nested functions
DO
$$
<< Parent >>
DECLARE
counter integer := 0;
BEGIN
counter := counter+1;
RAISE NOTICE 'the current value of counter (IN PARENT) is %', counter;
DECLARE
counter integer := 0;
BEGIN
counter := counter + 5;
RAISE NOTICE 'The current value of counter at subblocks is %', counter;
RAISE NOTICE 'The parent value of counter at subblocks is %', PARENT.counter;
END;
counter := counter + 5;
RAISE NOTICE 'the current value of counter (IN PARENT) is %', counter;
END;
$$
LANGUAGE PLPGSQL;
Returning ResultSet from function
CREATE OR REPLACE FUNCTION fn_order_by_date_pro() RETURNS SETOF orders AS
$$
BEGIN
RETURN QUERY SELECT * FROM orders limit 10;
END;
$$
LANGUAGE PLPGSQL;
SELECT * FROM fn_order_by_date_pro();
Conditional Statement inside functions
Default Parameters
CREATE OR REPLACE FUNCTION fn_which_is_greater
( x integer default 0, y integer default 0 ) RETURNS text AS
$$
BEGIN
IF x > y then
return ' x > y ';
else
return ' x < y ';
end if ;
END;
$$ LANGUAGE PLPGSQL;
SELECT fn_which_is_greater(4,3);
Switch Case Example
CREATE OR REPLACE FUNCTION fn_checker
( x integer default 0 ) RETURNS text AS
$$
BEGIN
CASE x
when 10 then
return 'value = 10';
when 20 then
return 'value = 20';
else
RETURN 'MORE';
END CASE;
END;
$$ LANGUAGE PLPGSQL;
SELECT fn_checker(30);
Loops in PLPGSQL
DO
$$
DECLARE
i_counter integer = 0;
BEGIN
LOOP
RAISE NOTICE '%', i_counter;
i_counter := i_counter+1;
EXIT WHEN
i_counter = 5;
END LOOP;
END;
$$ LANGUAGE PLPGSQL;
Loops in range exaple
DO
$$
BEGIN
FOR counter IN 1..5 BY 1
LOOP
RAISE NOTICE 'COUNTER : %', counter;
END LOOP;
END;
$$
LANGUAGE PLPGSQL;
Reverse Loops
DO
$$
BEGIN
FOR counter IN REVERSE 5..1 BY 1
LOOP
RAISE NOTICE 'COUNTER : %', counter;
END LOOP;
END;
$$
LANGUAGE PLPGSQL;
Iterating over result set
DO
$$
DECLARE
rec record ;
BEGIN
FOR rec in
select order_id, customer_id from orders LIMIT 10
LOOP
RAISE NOTICE '% %', rec.order_id, rec.customer_id;
END LOOP;
END;
$$ LANGUAGE PLPGSQL
Loop with Exit condition
DO
$$
DECLARE
i_counter int = 0;
BEGIN
LOOP
i_counter = i_counter + 1;
EXIT WHEN
i_counter > 20;
CONTINUE
WHEN MOD (i_counter,2) = 0;
RAISE NOTICE 'COUNTER : %', i_counter;
END LOOP;
END;
$$ LANGUAGE PLPGSQL;
Declaring arrays in PLPGSQL
DO
$$
DECLARE
arr1 int[] := array[1,2,3];
arr2 int[] := array[4,5,6,7,8];
var int;
BEGIN
FOREACH var IN ARRAY arr1||ARR2
LOOP
RAISE NOTICE '%', var;
END LOOP;
END;
$$ LANGUAGE PLPGSQL;
While Loop in PLPGSQL
CREATE OR REPLACE FUNCTION fn_while_loop_sum_all(x integer)
returns numeric as
$$
DECLARE
counter integer := 1;
sum_all integer := 0;
BEGIN
WHILE counter <= x
LOOP
sum_all := sum_all + counter;
counter := counter + 1;
END LOOP;
return sum_all;
END;
$$ language plpgsql
select fn_while_loop_sum_all(4);
Returning specific Query from column
CREATE OR REPLACE FUNCTION fn_api_products_by_names(p_pattern varchar)
RETURNS TABLE ( productname varchar, unitprice real )
AS
$$
BEGIN
RETURN QUERY
SELECT product_name,unit_price from products
where product_name like p_pattern;
END;
$$ LANGUAGE PLPGSQL;
SELECT * FROM fn_api_products_by_names('A%');
CREATE OR REPLACE FUNCTION fn_all_orders_greater() RETURNS SETOF order_details as
$$
DECLARE
r record;
BEGIN
for r in
select * from order_details where unit_price > 100
loop
return next r;
end loop;
return;
end;
$$ language plpgsql;
select * from fn_all_orders_greater();
If data not found condition
DO
$$
DECLARE
rec record;
orderid smallint = 1;
BEGIN
SELECT customer_id, order_date
FROM orders
INTO STRICT rec
WHERE order_id = orderid;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE EXCEPTION 'No order id was found';
END;
$$ LANGUAGE PLPGSQL;
Throwing execption on condition
DO
$$
DECLARE
rec record;
orderid smallint = 1;
BEGIN
SELECT customer_id, order_date
FROM orders
INTO STRICT rec
WHERE order_id > 1000;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
RAISE EXCEPTION 'Too many rows were found';
END;
$$ LANGUAGE PLPGSQL;
Throwing execption example
CREATE OR REPLACE FUNCTION fn_div_exception (x real, y real) RETURNS real as
$$
DECLARE
ret real;
BEGIN
ret := x / y;
return ret;
EXCEPTION
WHEN division_by_zero then
RAISE INFO 'division by zero error';
RAISE INFO 'ERROR % %', SQLSTATE, SQLERRM;
END;
$$ LANGUAGE PLPGSQL;
SELECT fn_div_exception(5,0);
Last updated