Forem

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

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide