DEV Community

Super Kai (Kazuya Ito)
Super Kai (Kazuya Ito)

Posted on • Edited on

PREPARE and EXECUTE statements in PostgreSQL

Buy Me a Coffee

A PREPARE statement:

  • can create a named query called a prepared statement to run it later with an EXECUTE statement. *The prepared statement is deleted after logout.

  • can only have a SELECT, INSERT, UPDATE or DELETE statement.

  • can have zero or more type-only parameters.

  • can have the aliases of type-only parameters e.g. $1, $2, etc.

  • cannot have multiple queries otherwise there is error.

  • cannot have named parameters e.g. num1 INT, num2 INT, etc otherwise there is error.

  • cannot have () just after the name if there are no parameters otherwise there is error so use () only if there are one or more parameters.

*The doc explains PREPARE statement.

*My answer explains how to show all the prepared statements in the current session.

*My answer explains how to delete the prepared statements in the current session.

An EXECUTE statement:

  • can run a prepared statement without a function, procedure or DO statement.

  • can dynamically run a SELECT, INSERT, UPDATE, DELETE, EXECUTE, PREPARE, CREATE TABLE statement, etc with a function, procedure or DO statement.

  • can be used in PL/pgSQL language(LANGUAGE plpgsql) for a function, procedure or DO statement.

  • cannot be used in SQL language(LANGUAGE SQL) otherwise there is error.

*The doc explains an EXECUTE statement.

*The doc explains the EXECUTE statement for PL/pgSQL language(LANGUAGE plpgsql).

*My answer explains when error occurs with EXECUTE statement.

For example, you create person table as shown below:

CREATE TABLE person ( id INT, name VARCHAR(20), age INT ); 
Enter fullscreen mode Exit fullscreen mode

Then, you insert 2 rows into person table as shown below:

INSERT INTO person (id, name, age) VALUES (1, 'John', 27), (2, 'David', 32); 
Enter fullscreen mode Exit fullscreen mode

Now, you can create the prepared statement my_pre with a PREPARE statement which can update age with id in person table as shown below:

PREPARE my_pre(INT, INT) AS UPDATE person SET age = $1 WHERE id = $2; 
Enter fullscreen mode Exit fullscreen mode

*Memos:

  • my_pre has 2 parameters as above but if you create my_pre with no parameters, you have to omit () otherwise there is error.

And now, you can run my_pre with an EXECUTE statement as shown below:

EXECUTE my_pre(45, 2); 
Enter fullscreen mode Exit fullscreen mode

*Memos:

  • If my_pre has no parameters, you must run it without () as EXECUTE my_pre; instead of EXECUTE my_pre(); otherwise there is error.

Then, age of David is updated to 45 as shown below:

postgres=# SELECT * FROM person; id | name | age ----+-------+----- 1 | John | 27 2 | David | 45 (2 rows) 
Enter fullscreen mode Exit fullscreen mode

And, you can use the EXECUTE statement with the EXECUTE statement to run my_pre in the PL/pgSQL function my_func() as shown below:

CREATE FUNCTION my_func() RETURNS VOID AS $$ BEGIN EXECUTE 'EXECUTE my_pre(18, 2)'; END; $$ LANGUAGE plpgsql; 
Enter fullscreen mode Exit fullscreen mode

*Memos:

  • EXECUTE my_pre(18, 2); gets error so you must use EXECUTE 'EXECUTE my_pre(18, 2)';.

  • My question and the answers(12) explain how to use the EXECUTE statement with the EXECUTE statement to dynamically run my_pre in my_func().

  • My post explains a PL/pgSQL function.

Then, calling my_func() updates age of David to 18 as shown below:

postgres=# SELECT my_func(); my_func --------- (1 row) postgres=# SELECT * FROM person; id | name | age ----+-------+----- 1 | John | 27 2 | David | 18 (2 rows) 
Enter fullscreen mode Exit fullscreen mode

And, you can use the EXECUTE statement with the UPDATE statement to update age with id in person table as shown below:

CREATE FUNCTION my_func() RETURNS VOID AS $$ BEGIN EXECUTE 'UPDATE person SET age = 33 WHERE id = 2'; END; $$ LANGUAGE plpgsql; 
Enter fullscreen mode Exit fullscreen mode

*Memos:

Or, you can use || as shown below. *|| can do concatenation with or without indentation:

CREATE FUNCTION my_func() RETURNS VOID AS $$ BEGIN EXECUTE 'UPDATE person SET age = ' || 33 || ' WHERE id = ' || 2; END; $$ LANGUAGE plpgsql; 
Enter fullscreen mode Exit fullscreen mode

Then, calling my_func() updates age of David to 33 as shown below:

postgres=# SELECT my_func(); my_func --------- (1 row) postgres=# SELECT * FROM person; id | name | age ----+-------+----- 1 | John | 27 2 | David | 33 (2 rows) 
Enter fullscreen mode Exit fullscreen mode

And, you can use a USING clause with an EXECUTE statement to dynamically update age with id in person table as shown below:

CREATE FUNCTION my_func(age INT, id INT) RETURNS VOID AS $$ BEGIN EXECUTE 'UPDATE person SET age = $1 WHERE id = $2' USING age, id; END; $$ LANGUAGE plpgsql; 
Enter fullscreen mode Exit fullscreen mode

Or:

CREATE FUNCTION my_func(age INT, id INT) RETURNS VOID AS $$ BEGIN EXECUTE 'UPDATE person SET age = $1 WHERE id = $2' USING $1, $2; END; $$ LANGUAGE plpgsql; 
Enter fullscreen mode Exit fullscreen mode

*Memos:

  • You must use $1 and $2 instead of age and id in '' of the EXECUTE statement otherwise there is error.

  • You cannot directly use age or $1 and id or $2 in '' of the EXECUTE statement without a USING clause otherwise there is the error as I explains it in my answer.

  • You can set age or $1 and id or $2 in the USING clause to use $1 and $2 in '' of the EXECUTE statement.

  • My question and the answers explains the difference between the function with and without an EXECUTE statement.

  • My answer(4) explains how to create a dynamic function with an EXECUTE and SELECT INTO statement, quote_ident(), quote_literal(), format().

  • My answer(5) explains how to create a dynamic function with an EXECUTE and INSERT statement, format() and USING clause:

Or, you can use || as shown below:

CREATE FUNCTION my_func(age INT, id INT) RETURNS VOID AS $$ BEGIN EXECUTE 'UPDATE person SET age = ' || age || ' WHERE id = ' || id; END; $$ LANGUAGE plpgsql; 
Enter fullscreen mode Exit fullscreen mode

Then, calling my_func() updates age of David to 56 as shown below:

postgres=# SELECT my_func(56, 2); my_func --------- (1 row) postgres=# SELECT * FROM person; id | name | age ----+-------+----- 1 | John | 27 2 | David | 56 (2 rows) 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)