On a broader level, PostgreSQL supports several procedural languages that help sustain data models that repeat previous values. PostgreSQL Stored Procedures support procedural operations, which are helpful while building powerful database apps — they increase their performance, productivity, and scalability. Like UDFs, stored procedures are a sequence of SQL statements available to apps that access an RDBMS.

In short, developing custom functions becomes easier using the PostgreSQL Stored Procedures. Moreover, once created, you can deploy stored procedures in any app based on your requirements. So, with this ultimate guide, you will learn about Stored Procedures in PostgreSQL in detail. And, through some workflow examples, you will also be able to apply the learnings in real-life situations, too. Let’s begin.

How to CREATE OR REPLACE PostgreSQL Stored Procedures?

In PostgreSQL, CREATE OR REPLACE PROCEDURE exists to create a new procedure or deploy a new definition in place of an existing one. To be able to CREATE OR REPLACE PROCEDURE, for a user in PostgreSQL, having a USAGE privilege on the language is a prerequisite.

The syntax to CREATE or REPLACE PostgreSQL Stored Procedures is given below:

CREATE [ OR REPLACE ] PROCEDURE
    name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
  { LANGUAGE lang_name
    | TRANSFORM { FOR TYPE type_name } [, ... ]
    | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
    | SET configuration_parameter { TO value | = value | FROM CURRENT }
    | AS 'definition'
    | AS 'obj_file', 'link_symbol'
    | sql_body
  }
  1. A procedure is generated in the schema if a schema name is provided. Otherwise, the existing schema captures the newly built one within itself.
  2. CREATE or REPLACE PROCEDURE can be used to change/replace the existing definition of the current procedure. The ownership and permissions will not change.
  3. You must have USAGE privilege on the argument types to build a procedure.
  4. The user who creates the procedure becomes the procedure’s owner.

The syntax given above is more generic to stored procedures. The one below is for PostgreSQL. 

create [or replace] procedure procedure_name(parameter_list)
language plpgsql
as $$
declare
-- variable declaration
begin
-- stored procedure body
end; $$
Code language: SQL (Structured Query Language) (sql)

Let’s break down the components In this syntax:

  • Write the name of the stored procedure after the create procedure keywords.
  • Set the parameters for the stored procedure. If not, a stored procedure can accept zero as well.
  • Mention plpgsql as the procedural language for the stored procedure.
  • Utilize the dollar-quoted string constant syntax to write the body of the stored procedure.

Note that parameters in stored procedures can’t have the out mode, but in and inout modes. As a stored procedure can’t return a value, you won’t be able to use the return statement with a value inside a store procedure like this:

return expression;
Code language: JavaScript (javascript)

But to stop the stored procedure immediately, you can utilitze the return statement without the expression as given: 

return;
Code language: SQL (Structured Query Language) (sql)
Streamline PostgreSQL Database Replication with Hevo

With Hevo, you can easily set up and manage replication processes, ensuring consistent and reliable data across your PostgreSQL databases.

Here’s how Hevo can help:

  • You can create a pipeline to automate data replication from 150+ sources.
  • Your data is automatically mapped and aligned with the schema of your target destination.
  • With Hevo, your data remains secure as it adheres to all major certifications, including GDPR, SOC II, and HIPAA.

Try Hevo and join a growing community of 2000+ data professionals who rely on us for seamless and efficient migrations.

Get Started with Hevo for Free!

Examples of Postgres Stored Procedure

1. Create_invoice: This stored procedure generates a new invoice by inserting data into an invoices table and calculating totals based on order details. 

Schema setup

CREATE TABLE orders (
  order_id INT64,
  customer_id INT64,
  total_amount NUMERIC
);
CREATE TABLE invoices (
  invoice_id INT64,
  customer_id INT64,
  invoice_date DATE,
  total_amount NUMERIC
);

Procedure

CREATE PROCEDURE create_invoice(p_order_id INT64)
BEGIN
  DECLARE v_customer_id INT64;
  DECLARE v_total_amount NUMERIC;
  -- Fetch order details
  SELECT customer_id, total_amount
  INTO v_customer_id, v_total_amount
  FROM orders
  WHERE order_id = p_order_id;
  -- Insert into invoices table
  INSERT INTO invoices (invoice_id, customer_id, invoice_date, total_amount)
  VALUES (
    (SELECT IFNULL(MAX(invoice_id), 0) + 1 FROM invoices), -- Auto-increment invoice_id
    v_customer_id,
    CURRENT_DATE(),
    v_total_amount
  );
END;

Usage: 

CALL create_invoice(101);

2. Is_paid: This procedure checks if an invoice has been paid based on a payments table.

Schema Setup:

CREATE TABLE payments (
  payment_id INT64,
  invoice_id INT64,
  payment_date DATE,
  amount_paid NUMERIC
);

Procedure:

CREATE PROCEDURE is_paid(p_invoice_id INT64)
BEGIN
  DECLARE v_total_amount NUMERIC;
  DECLARE v_amount_paid NUMERIC;
  -- Fetch the total amount for the invoice
  SELECT total_amount
  INTO v_total_amount
  FROM invoices
  WHERE invoice_id = p_invoice_id;
  -- Calculate the total payments made for the invoice
  SELECT IFNULL(SUM(amount_paid), 0)
  INTO v_amount_paid
  FROM payments
  WHERE invoice_id = p_invoice_id;
  -- Check if fully paid
  IF v_amount_paid >= v_total_amount THEN
    SELECT 'Paid' AS status;
  ELSE
    SELECT 'Unpaid' AS status;
  END IF;
END;

Usage:

CALL is_paid(201);

Workflow Example

Let’s use a stored_Procedure_Prac table to understand the PostgreSQL Stored Procedure better. We will use an online editor, OneCompiler, to write and run PostgreSQL queries for demo purposes.

Step 1: Create a table with the following inputs, as shown in the code block below.

create table stored_Procedure_Prac (
    id int generated by default as identity,
    name varchar(100) not null,
    balance dec(15, 2) not null,
    primary key(id)
);

insert into stored_Procedure_Prac(name, balance)
values('Don', 400000);

insert into stored_Procedure_Prac(name, balance)
values('Bob', 400000);

Step 2: Now run an SQL query to show the table.

select * from stored_Procedure_Prac;

The following shall be the result:

Output of SQL Query to Show Table
Output of SQL Query to Show Table

Step 3: The query below produces a stored procedure called prac_transfer, which transfers a specific amount of money from one account to another.

create or replace procedure prac_transfer(
   sender int,
   receiver int, 
   amount dec
)
language plpgsql    
as $$
begin
    -- subtracting the amount from the sender's account 
    update accounts 
    set balance = balance - amount 
    where id = sender;

    -- adding the amount to the receiver's account
    update accounts 
    set balance = balance + amount 
    where id = receiver;

    commit;
end;$$;

Step 4: Now call a stored procedure. Use the below-given query; a CALL statement is used.

call prac_transfer(1, 2, 1000);

The result would look like this:

Output of CALL Statement
Output of CALL Statement

Step 5: Now verify the results by running the following query.

SELECT * FROM stored_Procedure_Prac;
Query for Verifying Results
Query for Verifying Results

PostgreSQL Stored Procedure vs Function

A function returns a result, but a stored procedure does not. The reason is simple: the sole purpose of a stored procedure is to proceed with an action to complete it. Post that, the control is returned to the caller.

Do you know? Before PostgreSQL 11, stored procedures were functions that did not return data.

Using one of the PostgreSQL Stored Procedures examples query, let’s distinguish:

1. PostgreSQL Stored Procedures’ Query 

CREATE PROCEDURE deactivate_unpaid_accounts()
LANGUAGE SQL
AS $$
  UPDATE accounts SET active = false WHERE balance < 0;
$$;

For calling purposes, post PostgreSQL 11, we use the CALL statement as shown below:

CALL deactivate_unpaid_accounts();

2. PostgreSQL Function’s Query

CREATE FUNCTION deactivate_unpaid_accounts() RETURNS void
LANGUAGE SQL
AS $$
  UPDATE accounts SET active = false WHERE balance < 0;
$$;

For calling purposes, we used the SELECT statement, not CALL statement, as shown below:

SELECT deactivate_unpaid_accounts();

How Do Postgres Stored Procedures Affect Your Workflow (Advantages vs Disadvantages)?

AdvantagesDisadvantages
As stored Procedures can be reintroduced as often as possible, the number of visits between application and database servers is dramatically reduced. Using PostgreSQL Stored Procedures can slow down the software development process because stored procedure programming necessitates specific abilities that many developers lack. (This is a human resources challenge)
To retrieve the results and remove the waiting time to get a response, now the app simply has to issue a function call instead of sending SQL statements.It is difficult to manage workflow as many versions exist, and difficulty when debugging can not be undermined either.
The application’s performance is increased. The user-defined functions and stored procedures are now pre-combined in the PostgreSQL database server.A portability issue exists. Other DBMS systems like MySQL and MS SQL Server are not supported.

Transaction Control Capabilities in Postgres Stored Procedures

Transaction control capabilities in stored procedures are essential for ensuring data consistency and integrity during multiple related operations. These capabilities allow developers to group multiple SQL statements into a single unit of work, ensuring that either all operations succeed or none are applied (i.e., “atomicity”). Here’s an overview of transaction control in stored procedures:

Transaction Control Commands

  1. BEGIN TRANSACTION
    • Marks the start of a transaction. In some databases, this is implicit and does not need to be written explicitly.
  2. COMMIT
    • Finalizes the transaction, making all changes permanent. Once a COMMIT is issued, the changes made in the transaction are saved to the database.
  3. ROLLBACK
    • Reverts all changes made during the transaction. If something goes wrong (e.g., an error occurs in one of the SQL statements), the ROLLBACK command restores the database to its state before the transaction began.
  4. SAVEPOINT
    • Creates a point within the transaction to which you can later roll back without affecting the entire transaction. This allows for partial rollback.
  5. RELEASE SAVEPOINT
    • Removes a previously defined savepoint.

Benefits of Stored Procedures in PostgreSQL

Stored procedures offer significant benefits in terms of reusability and modularity:

  • Reusability: Stored procedures centralize business logic, reducing code duplication and ensuring consistency across multiple applications. Updates to the logic are made in one place, automatically benefiting all users.
  • Modularity: Complex tasks are broken down into smaller, manageable units. This promotes separation of concerns, making code easier to maintain and test. Stored procedures can encapsulate logic, improving organization and reducing errors.
  • Performance: Being precompiled, stored procedures often execute faster than dynamic SQL queries, reducing parsing overhead. They also minimize client-server communication.
  • Security: Access control is simplified by granting permissions to stored procedures instead of directly to data, ensuring sensitive information is protected.
  • Maintainability: Changes are easier to implement and version-controlled, enhancing long-term maintainability.

Conclusion

This article provided an in-depth knowledge of PostgreSQL Stored procedures. Through this article and a workflow example, we learned to CREATE OR REPLACE a stored procedure. We also discussed how Stored Procedures are different from Functions.

If you want to continue your learning of PostgreSQL Commands and operations, go through either of the two articles provided below:

  1. The Ultimate Guide to PostgreSQL Subquery for 2022
  2. PostgreSQL MAX() Function: Syntax, Working & Examples

Hevo is the only real-time ELT No-code Data Pipeline platform that cost-effectively automates data pipelines that are flexible to your needs. With integration with 150+ Data Sources (40+ free sources), we help you not only export data from sources & load data to the destinations but also transform & enrich your data, & make it analysis-ready.

Want to give Hevo a try? Sign up for a 14-day free trial and experience the feature-rich Hevo suite first hand. You may also look at the price, which will assist you in selecting the best plan for your requirements.

FAQ on PostgreSQL Stored Procedures

1. Does PostgreSQL have stored procedures?

Yes, PostgreSQL supports stored procedures and functions. Stored procedures can be written in various languages, such as PL/pgSQL, PL/Python, PL/Perl, and more.

2. How to execute the PostgreSQL stored procedure?

Execute a PostgreSQL stored procedure using the CALL statement. For example, CALL procedure_name(arguments);.

3. Is PostgreSQL faster than MySQL?

Performance depends on the use case. PostgreSQL is often faster for complex queries, data integrity, and concurrency, while MySQL may be faster for simple queries and read-heavy operations.

4. What is the difference between Postgres and MySQL stored procedures?

Postgres stored procedures use the CREATE PROCEDURE statement, which can be invoked with the CALL statement. MySQL-stored procedures also use CREATE PROCEDURE but differ in syntax and capabilities, particularly in error handling and control structures.

5. Where to CREATE PROCEDURE in PostgreSQL?

Create a procedure in PostgreSQL using the CREATE PROCEDURE statement within any SQL execution environment like psql, pgAdmin, or other database clients.

Yash Arora
Content Manager, Hevo Data

Yash is a Content Marketing professional with over three years of experience in data-driven marketing campaigns. He has expertise in strategic thinking, integrated marketing, and customer acquisition. Through comprehensive marketing communications and innovative digital strategies, he has driven growth for startups and established brands.