6 PostgreSQL-Functions and Procedures
6 PostgreSQL-Functions and Procedures
User-Defined Functions (UDFs) are custom functions created by users to extend the
functionality of a programming language or a database management system
(DBMS) like PostgreSQL. UDFs allow users to define their own functions tailored to
their specific requirements and execute them as if they were built-in functions.
Function is a named, reusable database object that encapsulates a set of SQL
statements or procedural code. Functions allow you to define custom logic and
calculations that can be invoked and reused within the database.
In PostgreSQL, functions are named blocks of code that perform specific tasks. They
allow you to encapsulate complex logic and reuse it throughout your database
queries.
Benefits of using functions in PostgreSQL
▪ Code Reusability: Functions allow you to encapsulate complex logic into a single
unit that can be reused across multiple queries or applications. This promotes
code reuse and reduces duplication, leading to more maintainable and modular
codebases.
▪ Performance Optimization: Functions can improve query performance by pre-
compiling and caching execution plans, especially for complex calculations or data
manipulations. They can also reduce network overhead by executing operations
directly on the database server.
▪ Security: Functions can enhance security by encapsulating sensitive logic or
access controls within the database layer. This reduces the risk of SQL injection
attacks and enforces data integrity and access policies at the database level.
▪ Modularity: Functions promote modularity by breaking down complex tasks into
smaller, manageable units. This makes it easier to develop, test, and maintain
database code, as changes to one function do not affect other parts of the
codebase.
▪ Abstraction: Functions abstract away implementation details, allowing users to
focus on the functionality provided by the function rather than how it is
implemented. This improves code readability and reduces the complexity of
queries by hiding the underlying logic.
▪ Ease of Maintenance: Functions facilitate code maintenance by providing a
centralized location for making updates or fixes. This ensures consistency
across queries and applications and simplifies the process of debugging
and troubleshooting issues.
▪ Cross-Platform Compatibility: Functions written in PostgreSQL can be easily
ported to other database systems that support similar procedural
languages, such as PL/pgSQL, PL/Python, etc. This allows for greater
flexibility and interoperability between different database environments.
▪ Parameterized Input: Functions accept input parameters, enabling you to
pass values to the function for processing. Parameterization adds flexibility
to your functions, allowing them to handle different scenarios and adapt to
varying input requirements. It enables you to create generic functions that
can be customized based on the input provided.
▪ Extended Functionality: UDFs enable users to extend the capabilities of the
database by adding custom functions that fulfill specific business or
application requirements. They can perform calculations, data
transformations, string manipulations, validations, and more.
Disadvantages of Functions
▪ Performance Overhead: Poorly designed or inefficient functions can introduce performance
overhead. Functions may require additional processing time due to their encapsulated logic,
parameter passing, and context switching. It is essential to optimize functions for performance,
considering factors such as query planning, indexing, and data access patterns.
▪ Debugging and Troubleshooting: Debugging functions can be more complex than debugging
regular SQL queries. When encountering errors or unexpected behavior in a function, it may be
challenging to pinpoint the exact cause within the function's logic or underlying procedural code.
Debugging tools and techniques specific to the chosen procedural language may be required.
▪ Dependency Management: Functions can have dependencies on other database objects, such as
tables, views, or other functions. Managing dependencies between functions and ensuring they
remain in sync with other objects can become challenging, especially in large, complex databases.
Modifications to dependent objects may require careful coordination and testing to avoid
breaking functionality.
▪ Limited Portability: Functions written in non-standard procedural languages, such as PL/pgSQL,
may have limited portability to other database systems. If you plan to migrate your database to a
different DBMS, you may need to rewrite or adapt your functions to the supported language of
the target database.
▪ Potential Complexity: Complex functions with intricate logic can be challenging to understand and
maintain over time. Overuse of functions or excessive nesting of function calls can lead to code
that is difficult to comprehend, making it harder for developers to maintain or enhance the
system.
▪ Versioning and Upgrades: Functions may need to be modified or updated
over time to accommodate changing requirements or fix issues. Managing
function versions and coordinating their upgrades across multiple
environments can be complex, particularly if the functions are used in
production systems.
▪ Security Considerations: Functions can introduce security risks if they are
not properly designed or secured. Poorly implemented functions may be
vulnerable to SQL injection attacks or unauthorized access to sensitive
data. It is crucial to follow best practices for function security, such as
parameter validation, proper access control, and avoiding dynamic SQL
generation.
▪ Learning Curve: Utilizing complex procedural languages like PL/pgSQL or
PL/Python requires developers to learn and become proficient in those
languages. This can introduce a learning curve, especially for developers
who are primarily familiar with SQL-based development.
The basic syntax for creating a UDF in PostgreSQL
CREATE OR REPLACE FUNCTION function_name ( argument_name
data_type)
RETURNS data_type
AS $$
DECLARE
-- Variable declarations
BEGIN
-- Function body
END;
$$ LANGUAGE language_name;
Explanation
▪ CREATE FUNCTION: Indicates that you are creating a new function.
OR REPLACE (optional): Allows you to replace an existing function with the
same name.
▪ function_name: The name of the function you are creating.
▪ argument_name, argument_type: The input arguments for the function, if
any.
▪ Data_type: The data type that the function returns.
▪ AS $$: Marks the beginning of the function body, which is written in the
specified procedural language.
▪ DECLARE: (Optional) Used for declaring variables within the function.
▪ BEGIN and END: Enclose the main body of the function, where you write
the logic.
▪ LANGUAGE language_name: Specifies the procedural language used in the
function body (e.g., plpgsql for PL/pgSQL)
Eg1:
Write pl/pgsql function which takes two integer arguments and returns
their sum.
Calling a user-defined function
PostgreSQL provides you with three ways to call a user-defined
function:
▪ Using positional notation
▪ Using named notation
▪ Using the mixed notation.
❑Using positional notation
This is the most basic method and involves supplying arguments in the
exact order they are defined in the function's parameter list.
Ex:
❑Named Notation: This approach offers more clarity and avoids
relying on argument order. You explicitly specify the parameter name
followed by the corresponding value within parentheses.
Calling Function
Write plpgsql function to Multiply two numbers
without parameters/arguments.
Calling Function
Eg 3
Given employee table below:
Calling Function
The OUT parameters are defined as part of the function arguments list
and are returned back as a part of the result.
Calling Function
INOUT Parameter:
The INOUT parameter is the combination IN and OUT parameters. It
means that the caller can pass a value to the function. The function
then changes the argument and passes the value back as a part of the
result.
Calling Function
Postgresql Stored procedure
Postgres stored procedures are routines that contain one or more SQL
statements designed to execute a task or set of tasks on a database
server. In PostgreSQL, a stored procedure is a named, reusable block of
code that encapsulates a set of SQL statements and can accept
parameters. Stored procedures are stored in the database and can be
called from various parts of an application.
In PostgreSQL, a stored procedure is a set of SQL statements that are
stored in the database and can be executed as a single function. Stored
procedures allow you to encapsulate complex business logic and
database operations within the database itself, promoting code reuse,
modularity, and consistency. Unlike functions, stored procedures can
support transaction control, including commits and rollbacks.
Benefits of stored procedures
▪ Code Reusability: Stored procedures allow you to write complex logic once and
reuse it throughout your application, improving code organization and
maintainability.
▪ Performance Optimization: Stored procedures are pre-compiled, which means
the database can execute them more efficiently than running the same set of SQL
statements repeatedly.
▪ Security and Access Control: You can grant or revoke permissions to execute
specific stored procedures, allowing for better control and security over your
data.
▪ Modularity: Stored procedures allow you to break down complex operations into
smaller, manageable pieces, improving code organization and maintainability.
▪ Encapsulation of Logic: Stored procedures encapsulate complex logic that might
involve multiple SQL statements, control structures (like loops and conditionals),
and transaction handling.
▪ Input/Output Parameters: Stored procedures can accept input parameters and
return output parameters, making them more flexible and powerful.
▪ Transaction Control: Stored procedures can manage transactions explicitly,
allowing for more complex transaction handling scenarios.
Disadvantages of stored Procedure
▪ Debugging: Debugging stored procedures can be more challenging
compared to application code. The tools and support for debugging SQL
code inside the database are often less mature and user-friendly than
those available for traditional programming languages.
▪ Maintenance: As stored procedures grow in complexity, they can become
harder to maintain. Changes to the business logic may require updates to
the stored procedures, which can be cumbersome, especially if the logic is
scattered across multiple procedures.
▪ Resource Utilization: Complex stored procedures can consume significant
database resources (CPU, memory), potentially impacting the performance
of the database server.
▪ Concurrency Issues: Improperly designed stored procedures may lead to
concurrency issues, such as deadlocks, especially when they involve
multiple transactions or complex locking mechanisms.
▪ Developer Skill Set: Not all developers are equally skilled in writing efficient
SQL and PL/pgSQL code. This can lead to poorly optimized stored
procedures that degrade performance.
▪ Deployment Complexity: Deploying changes to stored procedures requires
careful coordination to ensure that the database schema and application
code remain in sync. This can add complexity to the deployment process.
▪ Migration Difficulties: Changes to stored procedures can require careful
handling during database migrations, especially if the changes involve
altering procedure signatures or logic that existing application code
depends on.
▪ Security Concerns:
o Granting Permissions: Improper access control for procedures can
introduce security vulnerabilities if users are granted more privileges than
necessary.
oPotential for SQL Injection: If not written carefully, stored procedures can
be susceptible to SQL injection attacks if they accept untrusted user input.
Difference between stored procedure and User
Defined
❑Purpose:
function
• Stored Procedures: Designed to group multiple SQL statements, control flow (loops,
conditional statements), and error handling into a single, reusable unit. They are ideal for
encapsulating complex database operations or business logic.
• User-Defined Functions (UDFs): Primarily focus on performing calculations or
transformations on data and returning a single value. They are often used to extend
PostgreSQL's functionality with custom logic for specific tasks within queries.
❑Return Values:
• Stored Procedures: Do not necessarily return a value. Their primary function is to
execute a sequence of statements and potentially modify data within the database.
• UDFs: Must always return a value of a specific data type. This returned value can then be
used within expressions and queries like any other function.
❑Calling Mechanism:
• Stored Procedures: Executed using the CALL statement followed by the procedure name
and any required parameters in parentheses.
• UDFs: Invoked directly within SQL statements or expressions, just like any built-in
PostgreSQL function. You simply reference the function name followed by its arguments.
❑Functionality:
• Stored Procedures: Can perform various operations, including data manipulation (DML - INSERT,
UPDATE, DELETE), data retrieval (SELECT), control flow, and error handling using PL/pgSQL
programming language.
• UDFs: Limited to performing calculations or transformations based on the input data and
returning a single result. They typically involve SQL expressions or PL/pgSQL code for more
complex logic.
❑Transactions:
• Stored Procedures: Stored procedures can handle transactions explicitly using BEGIN, COMMIT,
and ROLLBACK statements.
• User-Defined Functions: Functions cannot handle transactions explicitly. They inherit the
transaction context of the calling environment.
❑Error Handling:
• Stored Procedures: Stored procedures can include more robust error handling and exception
management logic using constructs like EXCEPTION and RAISE.
• User-Defined Functions: Functions can also include error handling, but the options are more
limited compared to stored procedures.
❑Security:
• Stored Procedures: Stored procedures can be granted or revoked
permissions separately, allowing for more granular access control.
• User-Defined Functions: Functions inherit the permissions of the user
who created them.
❑Performance:
• Stored Procedures: Stored procedures are pre-compiled, which can
provide better performance for complex and frequently executed
logic.
• User-Defined Functions: Functions are compiled at runtime, which
may result in slightly lower performance compared to stored
procedures.
Syntax
To define a new stored procedure, you use the create procedure
statement with the following syntax:
create [or replace] procedure procedure_name(parameter_list)
language plpgsql
as $$
declare
-- variable declaration
begin
-- stored procedure body
end;
$$;
Explanation
First, specify the name of the stored procedure after the create procedure
keywords.
Second, define parameters for the stored procedure. A stored procedure can
accept zero or more parameters.
Third, specify plpgsql as the procedural language for the stored procedure.
Note that you can use other procedural languages for the stored procedure
such as SQL, C, etc.
Finally, use the dollar-quoted string constant syntax to define the body of the
stored procedure.
Parameters in stored procedures can have the in and inout modes. They
cannot have the out mode. A stored procedure does not return a value. You
cannot use the return statement with a value inside a store procedure like
this:
return expression;
Given accounts table below: