1. • PL/pgSQL Variables
• PL/pgSQL Constants
• PostgreSQL data types
Controlling the program flow, conditional statements, loops
2. P L / P G S Q L VA R I A B L E S
• A PL/pgSQL variable is a meaningful name for a memory location. A
variable holds a value that can be changed through the block or function. A
variable is always associated with a particular data type.
• You must declare it in the declaration section of the PL/pgSQL block before
using.
variable_name data_type[:=expression];
Counter integer := 0;
3. variable_name data_type[:=expression];
• In this syntax:
• First, specify the name of the variable. It is a good practice to assign a
meaningful name to a variable. For example, instead of naming a
variable i you should use index or counter.
• Second, associate a specific data type with the variable. The data type
can be any valid PostgreSQL data type such
as INTEGER, NUMERIC, VARCHAR and CHAR.
• Third, optionally assign a default value to a variable. If you don’t, the
initial value of the variable is initialized to NULL.
• Notice that PostgreSQL evaluates the default values and set them for
the variables when the block is entered. Exa.
4. DO $$
DECLARE
cnt NUMERIC:=1;
first_name VARCHAR(50):='John';
last_name VARCHAR(50):='Doe';
payment NUMERIC(11,2):=20.5;
BEGIN
RAISE NOTICE'% % % has been paid % USD’, cnt,first_name,last_name,
payment;
END; $$
Note that you can use either := or = assignment operator to initialize and assign a value to a variable.
5.
6. P L / P G S Q L C O N S TA N T S
• The values of constants cannot be changed once they are initialized.
• The following are reasons to use constants.
• First, the constants make the code more readable e.g., imagine that we have a
formula as follows:
• selling_price=net_price+net_price*0.1;
• What does 0.1 means? It can be interpreted to anything. But, when we use the
following formula, we know the meaning of the calculation of the selling price that
equals to net price plus value-added tax (VAT).
• selling_price=net_price+net_price*VAT;
• Second, the constants reduce the maintenance efforts. constants example
7. D E C L A R I N G C O N S TA N T S Y N TA X
To declare a constant in PL/pgSQL, you use the following syntax:
• constant_name CONSTANT data_type:=expression;
• PI CONSTANT float =3.14;
Let’s examine each component of the syntax in more detail:
• First, specify the constant name. By convention, it is in the uppercase form
such as VAT and DISCOUNT.
• Second, put the CONSTANT keyword and specify the data type that the
constant is associated with.
• Third, initialize a value for the constant.
8. P L / P G S Q L S E L E C T I N T O
• We can use PL/pgSQL SELECT INTO statement to fetch data of a single row from a
table into variables.
SELECT
select_list
INTO
variable_list
FROM
table_name
WHERE
condition;
The number of columns in the variable_list must be the same as the number of variables in
the select_list. In addition, their corresponding data type must be compatible.
9. DO $$
DECLARE
actorf_name varchar(10);
actorl_name varchar(10);
BEGIN
select actfname,actlname
into actorf_name,actorl_name
from actor
where actid=102;
RAISE NOTICE 'The actors details: %%', actorf_name,actorl_name;
END; $$
10. Copying data types
• PL/pgSQL enables you to define a variable with a data type that
references to the data type of a column of a table or the data type
of another variable using %type:
• The %type provides the data type of a table column or another
variable.
variable_name table_name.column_name%TYPE;
Fname student.std_Fname%TYPE;
variable_name variable%TYPE;
Lname Fneme%TYPE;
11. Assigning aliases to variables
• PostgreSQL allows you to define an alias for any
variable as follows:
• new_name ALIAS FOR old_name;
• user_name ALIAS FOR f_name;
12. P L / P G S Q L R O W T Y P E S ( % R O W T Y P E )
• To store the whole row of a result set returned by the ’select into’ statement,
you use the row-type variable or row variable.
• You can declare a variable that has the same datatype as the datatype of the
row in a table by using the following syntax:
row_variable table_name%ROWTYPE;
row_variable view_name%ROWTYPE;
14. P L / P G S Q L R E C O R D T Y P E S
• PostgreSQL uses record type variables which simply act as placeholders for
rows of a result set.
• To declare a record variable, you use a variable name followed by
the record keyword like this:
variable_name record;
• Unlike a row-type variable, a record variable does not have a predefined
structure. The structure of a record variable is determined when
the select or for statement assigns an actual row to it.
17. T Y P E S
• PostgreSQL supports the following data types:
• Boolean
• Character types such as char, varchar, and text.
• Numeric types such as integer and floating-point number.
• Temporal types such as date, time, timestamp, and interval
• UUID for storing Universally Unique Identifiers
• Array for storing array strings, numbers, etc.
• JSON stores JSON data
• hstore stores key-value pair
• Special types such as network address and geometric data.
18.
19.
20. N U M E R I C ( P R E C I S I O N , S C A L E )
• In this syntax, the precision is the total number of digits and the scale is the
number of digits in the fraction part. For example, the number 1234.567 has the
precision 7 and scale 3.
• The NUMERIC type can hold a value up to 131,072 digits before the decimal
point 16,383 digits after the decimal point.
• The scale of the NUMERIC type can be zero or positive. The following shows the
syntax of NUMERIC type with scale zero:
• NUMERIC(precision)
21. • If you omit both precision and scale, you can store any precision and
scale up to the limit of the precision and scale mentioned above.
NUMERIC
If precision is not required, you should not use the NUMERIC type because
calculations on NUMERIC values are typically slower than integers, floats,
and double precisions.
22. B O O L E A N
• A Boolean data type can hold one of three possible values: true, false
or null.
• You use boolean or bool keyword to declare a column with the Boolean
data type.
When you insert data into a Boolean column, PostgreSQL converts it to
a Boolean value
• 1, yes, y, t, true values are converted to true
• 0, no, false, f values are converted to false.
• When you select data from a Boolean column, PostgreSQL converts
the values back e.g., t to true, f to false and space to null.
23.
24. C H A R A C T E R
• PostgreSQL provides three character data types: CHAR(n), VARCHAR(n),
and TEXT
• CHAR(n) is the fixed-length character with space padded. If you insert a
string that is shorter than the length of the column, PostgreSQL pads
spaces. If you insert a string that is longer than the length of the column,
PostgreSQL will issue an error.
• VARCHAR(n) is the variable-length character
string. With VARCHAR(n), you can store up to n characters. PostgreSQL
does not pad spaces when the stored string is shorter than the length of the
column.
• TEXT is the variable-length character string. Theoretically, text data is a
character string with unlimited length.
25. P L / P G S Q L A S S E R T S TAT E M E N T
• The assert statement is a useful shorthand for inserting debugging checks into PL/pgSQL
code.
• The following illustrates the syntax of the assert statement:
assert condition [, message];
1) condition
• The condition is a Boolean expression that is expected to always return true.
• If the condition evaluates to true, the assert statement does nothing.
• In case the condition evaluates to false or null, PostgreSQL raises
an assert_failure exception.
26. P L / P G S Q L A S S E R T S TAT E M E N T
2) message
• The message is optional.
• If you don’t pass the message, PostgreSQL uses the “assertion failed”
message by default. In case you pass the message to the assert statement,
it will use it to replace the default message.
• Note that you should use the assert statement solely for detecting bugs, not
for reporting.
• To report a message or an error, you use the raise statement instead.
3 / 9 / 2 0 2 3 28
27. 3 / 9 / 2 0 2 3 29
do $$
declare
film_count integer;
begin
select count(*)
into film_count
from film;
assert film_count > 0, 'Film not found, check the
film table';
end$$;
28. R E P O R T I N G M E S S A G E S
• To raise a message, you use the raise statement as follows:
raise level format;
1. Level
PostgreSQL provides the following levels:
• debug
• log
• notice
• info
• warning
• exception
3 / 9 / 2 0 2 3 30
29. 2. Format
• The format is a string that specifies the message. The format uses percentage ( %)
placeholders that will be substituted by the arguments.
do $$
begin
raise info 'information message %', now();
raise log 'log message %', now();
raise debug 'debug message %', now();
raise warning 'warning message %', now();
raise notice 'notice message %', now();
end $$;
3 / 9 / 2 0 2 3 31
30. Raising errors
• To raise an error, you use the exception level after the raise statement. Note
that raise statement uses the exception level by default.
do $$
declare
email varchar(255) := 'info@postgresqltutorial.com';
begin
-- check email for duplicate
-- ...
-- report duplicate email
raise exception 'duplicate email: %', email
using hint = 'check the email again';
end $$;
3 / 9 / 2 0 2 3 32
32. PL/pgSQL IF Statement
• The IF statement is used to execute a command conditionally. PL/pgSQL
provides you with three forms of the IF statements.
The simplest form of PL/pgSQL IF statement
• The IF statement executes statements if a conditionis true. If the condition
evaluates to false, the control is passed to the next statement after
the END IF part. The following illustrates the simplest form of
the IF statement:
If condition THEN
statement;
END IF;
The condition is a boolean expression that evaluates to true or f
alse.
33.
34. DO $$
DECLARE a integer := 10;
b integer := 20;
BEGIN
IF a > b THEN
RAISE NOTICE 'a is greater than b';
END IF;
IF a < b THEN
RAISE NOTICE 'a is less than b';
END IF;
IF a = b THEN
RAISE NOTICE 'a is equal to b';
END IF;
END $$;
35. PL/pgSQL IF THEN ELSE statement
• The IF THEN ELSE statement executes a command when the
condition is true and it executes an alternative command when
the condition is false. The following illustrates the syntax of
the IF THEN ELSE statement:
IF condition THEN
statements;
ELSE
alternative-statements;
END IF;
36.
37. DO $$
DECLARE
a integer:=10;
b integer:=20;
BEGIN
IF a>b THEN
RAISE NOTICE 'a is greater than b';
ELSE
RAISE NOTICE 'a is not greater than b';
END IF;
END $$;
38. PL/pgSQL IF THEN ELSIF THEN ELSE statement
IFcondition-1THEN
if-statement;
ELSIFcondition-2THEN
elsif-statement-2
...
ELSIFcondition-nTHEN
elsif-statement-n;
ELSE
else-statement;
END IF;
39.
40. DO $$
DECLARE
a integer := 10;
b integer := 10;
BEGIN
IF a > b THEN
RAISE NOTICE 'a is greater than b';
ELSIF a < b THEN
RAISE NOTICE 'a is less than b';
ELSE
RAISE NOTICE 'a is equal to b';
END IF;
END $$;
41. PL/pgSQL CASE Statement
• Besides the IF statement, PostgreSQL provides you
with CASE statements that allow you to execute a block of code
conditionally.
• There are two forms of the CASE statement:
• simple
• searched CASE statements.
42. Simple CASE
CASE search-expression
WHEN expression [, expression [ ... ]] THEN statements [
WHEN expression [, expression [ ... ]] THEN statements ... ]
[ ELSE statements ]
END CASE;
3/9/2023 44
43. CREATE FUNCTION case1 (val integer)
RETURNS text
LANGUAGE PLPGSQL
AS
$$
BEGIN
CASE val
WHEN 1 THEN
RETURN ‘ one’;
WHEN 2 THEN
RETURN ' two';
WHEN 3 THEN
RETURN ‘ three';
ELSE
RETURN 'other value than 1,2,3';
END CASE;
END; $$;
3/9/2023 45
45. Searched CASE
• The searched form of CASE provides conditional execution
based on truth of Boolean expressions.
• Each WHEN clause's boolean-expression is evaluated in turn,
until one is found that yields true.
• Then the corresponding statements are executed, and then
control passes to the next statement after END CASE.
47. CASE
WHEN x BETWEEN 0 AND 10 THEN
msg := 'value is between zero and ten';
WHEN x BETWEEN 11 AND 20 THEN
msg := 'value is between eleven and twenty';
END CASE;
48. PL/pgSQL LOOP statement
Sometimes, you need to execute a block of statements
repeatedly until a condition becomes true.
To do this, you use the PL/pgSQL LOOP statement.
[<<label>>]
LOOP
Statements;
EXIT [<<label>>] WHEN condition;
END LOOP;
3/9/2023 50
49. CREATE OR REPLACE FUNCTION fibonacci(n INTEGER) RETURNS INTEGER AS $$
DECLARE
counter INTEGER:=0;
i INTEGER:=0;
j INTEGER:=1;
BEGIN
IF(n<1)THEN
RETURN 0;
END IF;
LOOP
EXIT WHEN counter=n;
counter:=counter+1;
SELECT j,i+j INTO i,j;
END LOOP;
RETURN i;
END; $$ LANGUAGE plpgsql;
3 / 9 / 2 0 2 3 51
50. P L / P G S Q L W H I L E L O O P
• The WHILE loop statement executes a block of statements until a
condition evaluates to false.
• In the WHILE loop statement, PostgreSQL evaluates the condition before
executing the block of statements.
• If the condition is true, the block of statements is executed until it is
evaluated to false.
• The following flowchart illustrates the WHILE loop statement.
51.
52. The following is the syntax of the WHILE loop statement.
[<<label>>]
WHILE condition LOOP
statements;
END LOOP;
53. CREATE OR REPLACE FUNCTION fibonacci(n INTEGER)
RETURNS INTEGER AS $$
DECLARE
counter INTEGER:=0;
i INTEGER:=0;
j INTEGER:=1;
BEGIN
IF(n<1)THEN
RETURN 0;
END IF;
WHILE counter<= n LOOP
counter :=counter + 1;
SELECT j,i+j INTO i, j;
END LOOP;
RETURN i;
END; $$
56. The following code uses the for loop statement to iterate over largest 10 employee id:
do
$$
declare
f record;
begin
for f in select employee_id, full_name
from employees
order by employee_id desc, full_name
limit 10
loop
raise notice '% % ', f.employee_id, f.full_name;
end loop;
end;
$$;
57.
58. do $$
declare
sort_type smallint := 1;
rec_count int := 10;
rec record;
query text;
begin
query := 'select full_name, employee_id from employees
';
if sort_type = 1 then
query := query || 'order by employee_id desc ';
elsif sort_type = 2 then
query := query || 'order by length(full_name) desc ';
else
raise 'invalid sort type %s', sort_type;
end if;
query := query || ' limit $1';
for rec in execute query using rec_count
loop
raise notice '% %', rec.employee_id, rec.full_name;
end loop;
end;
Editor's Notes
1.1 Introduction to PLSQL
1.2 PL/PgSqL: Datatypes, Language structure
1.3 Controlling the program flow, conditional statements, loops
1.4 Stored Procedures
1.5 Stored Functions
1.6 Handling Errors and Exceptions
1.7 Cursors
1.8 Triggers
Notice that the DO statement does not belong to the block. It is used to execute an anonymous block.
The PostgreSQL SELECT INTO statement creates a new table and inserts data returned from a query into the table.
If the SELECT statement returns more than one row, Oracle will raise the TOO_MANY_ROWS exception. If the SELECT statement does not return any row, Oracle will raise the NO_DATA_FOUND exception.
Third, you can refer the type of variables to data type of function arguments to create polymorphic functions since the type of internal variables can change from one call to the next.
-- select actor with id 10
In Postgres 10 or later consider an IDENTITY column instead of a serial
Notice that PostgreSQL introduced the assert statement since version 9.5. Check your PostgreSQL version before using it.
Enable / Disable Assertions
PostgreSQL provides the plpgsql.check_asserts configuration parameter to enable or disable assertion testing. If you set this parameter to off, the assert statement will do nothing.
Notice that not all messages are reported back to the client. PostgreSQL only reports the info, warning, and notice level messages back to the client. This is controlled by client_min_messages and log_min_messages configuration parameters.
The statement is a statement that will be executed if the condition is true. It can be any valid statement, even another IF statement. An IF code statement is placed inside another IF statement is called a nested-IF statement.
The following flowchart illustrates the simple IF statement
In this example, we declare two variables a and b. In the body of the block, we compare the value of a and b using the comparison operator >, < and = in the boolean expressions of the IF statements and print out the corresponding message.
Because a is less than b, we receive the following output when we execute the block:
NOTICE: a is less than b
Because the expression a > b is false, the statement in the ELSE clause is executed. We get the following output:
NOTICE: a is not greater than b
The IF and IF THEN ELSE statements allow you to have just one condition to evaluate. However, with this form of the IF statement, you may have multiple conditions to evaluate.
The then condition is true, the corresponding statement in that branch is executed. For example, if the condition-1, condition-2, etc., is true then the corresponding statement: if-statement, elseif-statement-2, etc., will execute. In case one condition is true, PostgreSQL will stop evaluating the underneath conditions.
If all conditions are false, the statements in the last ELSE branch are executed.
The following flowchart illustrates the IF ELSIF ELSE statement.
In this example, because a is equal to b, the statement in the ELSE branch is executed.
1
NOTICE: aisequaltob
In this tutorial, you have learned three forms of the IF statement to execute a statement based on a certain condition.
Notice that you should not confuse about the CASE statement and CASE expression.
The CASE expression evaluates to a value, while the CASE statement executes statements based on condition.
select case1(1);
This form of CASE is entirely equivalent to IF-THEN-ELSIF, except for the rule that reaching an omitted ELSE clause results in an error rather than doing nothing.
The LOOP statement is also referred to as an unconditional loop statement because it executes the statements until the condition in the EXIT statement evaluates to true. Note that the condition specified after the WHEN keyword in the EXIT statement is a Boolean expression that evaluates to true or false.
Loop statements can be nested. A LOOP statement is placed inside another LOOP statement is known as a nested loop. In this case, you need to the loop label to specify explicitly which loop you want to terminate in the EXIT statement.
Fibonacci sequence
The Fibonacci function accepts an integer and returns the nth Fibonacci number.
By definition, Fibonacci numbers are the sequence of integers starting with 0 and 1, and each subsequent number is the sum of the previous two numbers, for example, 1, 1, 2 (1+1), 3 (2+1), 5 (3 +2), 8 (5+3), …
In the declaration section, the counter variable is initialized to zero (0). Inside the loop, when counter equals n, the loop exits. The statement:
1
SELECTj,i+jINTOi, j;
swaps i and j at the same time without using a temporary variable.
$1 is a reference to the first argument of the function.