PLPGSQL - How to execute dynamic query?

2 min read 04-10-2024
PLPGSQL - How to execute dynamic query?


Unlocking Dynamic Queries in PL/pgSQL: A Practical Guide

Problem: You need to execute SQL queries within your PL/pgSQL functions, but the exact query structure can vary based on input parameters or runtime conditions. This is where dynamic queries come into play.

Rephrased: Imagine you're building a function to fetch data from a database table. You want the function to be flexible enough to handle different search criteria provided by the user. Dynamic queries allow you to construct and execute SQL queries on the fly, adapting them to these changing conditions.

Scenario & Original Code:

Let's say you have a table called products with columns product_id, name, and category. You want a PL/pgSQL function that returns products based on a given category.

CREATE OR REPLACE FUNCTION get_products_by_category(category_name TEXT)
RETURNS TABLE(product_id INT, name TEXT) AS $
BEGIN
    RETURN QUERY EXECUTE 'SELECT product_id, name FROM products WHERE category = $1';
END;
$ LANGUAGE plpgsql;

SELECT * FROM get_products_by_category('Electronics');

Explanation:

  • We define a function get_products_by_category that takes a category_name as input.
  • RETURN QUERY EXECUTE is the key here. It allows us to execute a dynamic query.
  • The $1 within the query string is a placeholder for the category_name parameter passed to the function.
  • The EXECUTE statement replaces $1 with the actual value of category_name before executing the query.

Key Insights:

  • Flexibility: Dynamic queries allow you to construct queries based on runtime conditions.
  • Security: Be mindful of SQL injection vulnerabilities. Use parameterization (like $1) to safely pass values into your queries.
  • Efficiency: Avoid unnecessary string concatenation. PL/pgSQL offers mechanisms like format to construct queries efficiently.

Additional Examples:

  • Dynamic Table Selection:
    CREATE OR REPLACE FUNCTION get_data(table_name TEXT, id INT)
    RETURNS TABLE(data TEXT) AS $
    BEGIN
        RETURN QUERY EXECUTE format('SELECT * FROM %I WHERE id = %L', table_name, id);
    END;
    $ LANGUAGE plpgsql;
    
  • Conditional WHERE Clauses:
    CREATE OR REPLACE FUNCTION get_products(filter_by TEXT)
    RETURNS TABLE(product_id INT, name TEXT) AS $
    BEGIN
        IF filter_by IS NOT NULL THEN
            RETURN QUERY EXECUTE format('SELECT product_id, name FROM products WHERE category = %L', filter_by);
        ELSE
            RETURN QUERY EXECUTE 'SELECT product_id, name FROM products';
        END IF;
    END;
    $ LANGUAGE plpgsql;
    

Benefits:

  • Reduced code duplication: Avoid writing multiple functions for different scenarios.
  • Enhanced maintainability: Changes to the database schema or query logic only need to be updated in one place.
  • Increased flexibility: Dynamic queries adapt to changing requirements, allowing for more powerful applications.

References & Resources:

Conclusion:

Dynamic queries are a powerful tool in your PL/pgSQL arsenal. By utilizing them effectively and responsibly, you can build more flexible, adaptable, and efficient database applications. Remember to prioritize security by using parameterized queries and carefully validating your input data.