43

What are the difference between perform and execute on PL/pgSQL?

From the manual:

Sometimes it is useful to evaluate an expression or SELECT query but discard the result, for example when calling a function that has side-effects but no useful result value. To do this in PL/pgSQL, use the PERFORM statement.

But, when I'm trying something like:

perform 'create table foo as (select 1)';

Nothing happens. Although this query should have side effects (creating table), and the result can be discarded.

I think I get 1 thing right: in order to run functions I can use perform:

perform pg_temp.addInheritance(foo);
Guy s
  • 1,586
  • 3
  • 20
  • 27
  • 1
    `perform` replaces `select`. it is select ignoring the return, you can't `select 'create table foo as (select 1)';` – Vao Tsun Mar 21 '17 at 08:01
  • In other words, it cannot make any change to the database? – Guy s Mar 21 '17 at 08:02
  • 1
    it can, same way `select` can. no more no less. Eg `select pg_create_restore_point('change to db');` or select 1 from dblink_exec('local', 'create table...') as (i int)` or so – Vao Tsun Mar 21 '17 at 08:06

3 Answers3

61

PERFORM is plpgsql command used for calls of void functions. PLpgSQL is careful about useless SELECT statements - the SELECT without INTO clause is not allowed. But sometimes you need to call a function and you don't need to store result (or functions has no result). The function in SQL is called with SELECT statement. But it is not possible in PLpgSQL - so the command PERFORM was introduced.

CREATE OR REPLACE FUNCTION foo()
RETURNS void AS $$
BEGIN
  RAISE NOTICE 'Hello from void function';
END;
$$ LANGUAGE plpgsql;

-- direct call from SQL
SELECT foo();

-- in PLpgSQL
DO $$
BEGIN
  SELECT foo(); -- is not allowed
  PERFORM foo(); -- is ok
END;
$$;

The PERFORM statements execute a parameter and forgot result.

Your example perform 'create table foo as (select 1)';

is same like SELECT 'create table foo as (select 1)'. It returns a string "create table foo as (select 1)" and this string is discarded.

The EXECUTE statement evaluate a expression to get string. In next step this string is executed.

So EXECUTE 'create table ' || some_var || '(a int)'; has two steps

  1. evaluate expression 'create table ' || some_var || '(a int)'
  2. if some_var is mytab for example, then execute a command create table mytab(a int)

The PERFORM statement is used for function calls, when functions are not used in assignment statement. The EXECUTE is used for evaluation of dynamic SQL - when a form of SQL command is known in runtime.

Yuri Astrakhan
  • 8,808
  • 6
  • 63
  • 97
Pavel Stehule
  • 42,331
  • 5
  • 91
  • 94
6

Further next line in docs you quote:

This executes query and discards the result. Write the query the same way you would write an SQL SELECT command, but replace the initial keyword SELECT with PERFORM.

Emphasis mine

execute in its turn executes dynamic query (same docs above)

Vao Tsun
  • 47,234
  • 13
  • 100
  • 132
2

I recently had a case where I needed to set specific constraints to DEFERRED and found something interesting.

 - EXECUTE 'SET CONSTRAINTS fk_a DEFERRED';
 - PERFORM 'SET CONSTRAINTS fk_a DEFERRED';

Both EXECUTE and PERFORM executed the statements without error but only EXECUTE persisted the action for the rest of the code. Somehow, it looks like PERFORM runs in it's own transaction "bubble".

In my case I had two tables a and b and a FK (the real stuation is much more complex). There was a need to insert the data out of the parent/child order and for that we needed the constraint DEFERRED. Using the PERFORM we had a foreign key violation, with EXECUTE we didn't.

Emon46
  • 1,506
  • 7
  • 14
  • Did you ever learn anything more about this? I'm not facing this problem, nor anything similar, but it seems mightly interesting – Mâtt Frëëman Feb 07 '23 at 15:58