DEV Community

Pranav Bakare
Pranav Bakare

Posted on

Dynamic SQL in Oracle SQL | Best Explanation

Dynamic SQL in Oracle SQL

Dynamic SQL in Oracle allows you to build and execute SQL statements at runtime. This approach is useful when you need to execute SQL queries whose structure isn't known until runtime. This capability provides flexibility, enabling you to construct queries dynamically based on user inputs, system conditions, or business logic.

In Oracle, there are several ways to implement dynamic SQL, and the key components involved are:

Key Concepts in Dynamic SQL:

  1. EXECUTE IMMEDIATE

Purpose: It is used to execute dynamically built SQL statements at runtime.

How it Works: You construct a SQL statement as a string, and then use EXECUTE IMMEDIATE to execute that string as if it were a static SQL statement.

Example:

DECLARE
table_name VARCHAR2(50) := 'employees';
v_sql VARCHAR2(1000);
v_count NUMBER;
BEGIN
v_sql := 'SELECT COUNT(*) FROM ' || table_name;
EXECUTE IMMEDIATE v_sql INTO v_count;
DBMS_OUTPUT.PUT_LINE('Total count: ' || v_count);
END;

In this example, v_sql holds the dynamic SQL query. The query is constructed at runtime, and EXECUTE IMMEDIATE runs it.

  1. Bind Variables

Purpose: Bind variables are placeholders in SQL queries that are replaced with actual values at runtime. They enhance performance by allowing SQL statements to be reused without parsing them again.

How it Works: Bind variables also help prevent SQL injection attacks, as they ensure that inputs are treated as data, not executable SQL.

Example:

DECLARE
v_sql VARCHAR2(1000);
v_dept_id NUMBER := 10;
v_count NUMBER;
BEGIN
v_sql := 'SELECT COUNT(*) FROM employees WHERE department_id = :dept_id';
EXECUTE IMMEDIATE v_sql INTO v_count USING v_dept_id;
DBMS_OUTPUT.PUT_LINE('Count: ' || v_count);
END;

Here, :dept_id is the bind variable. It gets replaced with the value of v_dept_id at runtime.

  1. REF CURSOR (SYS_REFCURSOR)

Purpose: A REF CURSOR is a pointer to a result set. It is useful for returning query results dynamically when you don’t know the structure of the result set beforehand.

How it Works: In dynamic SQL, the result set is returned as a cursor variable (SYS_REFCURSOR). This is especially useful when querying dynamic tables or results whose structure changes at runtime.

Example:

DECLARE
v_cursor SYS_REFCURSOR;
v_sql VARCHAR2(1000);
v_name VARCHAR2(100);
BEGIN
v_sql := 'SELECT first_name FROM employees WHERE department_id = :dept_id';
OPEN v_cursor FOR v_sql USING 10; -- dept_id = 10
LOOP
FETCH v_cursor INTO v_name;
EXIT WHEN v_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Employee: ' || v_name);
END LOOP;
CLOSE v_cursor;
END;

Here, a SYS_REFCURSOR is used to dynamically open a cursor for the query. The result is then processed in a loop.

  1. DBMS_SQL Package

Purpose: This package provides a more advanced and flexible way to handle dynamic SQL. It is often used when you need to bind multiple variables or when the SQL is very complex.

How it Works: With DBMS_SQL, you can handle SQL queries, bind variables, and manage cursors more granularly.

Example:

DECLARE
v_cursor INTEGER;
v_sql VARCHAR2(1000);
v_count NUMBER;
BEGIN
v_sql := 'SELECT COUNT(*) FROM employees WHERE department_id = :dept_id';
v_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_cursor, v_sql, DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(v_cursor, ':dept_id', 10);
DBMS_SQL.EXECUTE(v_cursor);
DBMS_SQL.FETCH_ROWS(v_cursor, v_count);
DBMS_SQL.CLOSE_CURSOR(v_cursor);
DBMS_OUTPUT.PUT_LINE('Count: ' || v_count);
END;

This approach is more flexible and is often used in cases where you need to work with multiple bind variables or complex queries.

Other Key Aspects:

  1. Dynamic DDL (Data Definition Language)

Dynamic DDL refers to executing DDL statements (such as CREATE, ALTER, DROP, etc.) dynamically. Since DDL statements generally don't support bind variables, they are executed using EXECUTE IMMEDIATE.

Example:

DECLARE
table_name VARCHAR2(50) := 'new_table';
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE ' || table_name || ' (id NUMBER, name VARCHAR2(100))';
END;

In this case, the table name is dynamically inserted into the CREATE TABLE statement.

  1. Error Handling in Dynamic SQL

When executing dynamic SQL, you should always handle exceptions properly to avoid runtime errors.

Example with Error Handling:

BEGIN
EXECUTE IMMEDIATE 'SELECT * FROM non_existing_table';
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
END;

Here, the SQLERRM function is used to capture and display any errors that occur during the execution of dynamic SQL.

  1. Plan Caching

Oracle can cache the execution plan for static SQL queries, but for dynamic SQL, the SQL statement is parsed and compiled each time it is executed unless bind variables are used effectively. This can impact performance, especially with frequent queries.

  1. SQL Injection Prevention

Since dynamic SQL constructs queries from user inputs, there’s a risk of SQL injection. The best way to prevent SQL injection is to always use bind variables. They ensure that user input is treated as data, not executable SQL code.

Summary of Key Dynamic SQL Techniques:

  1. EXECUTE IMMEDIATE: Used to execute dynamic SQL queries that are built at runtime.

  2. Bind Variables: Allow dynamic SQL queries to use placeholders that are substituted with actual values at runtime.

  3. REF CURSOR (SYS_REFCURSOR): Used to return a dynamic result set (cursor) from a dynamically generated query.

  4. DBMS_SQL: A more flexible package for working with complex dynamic SQL queries, multiple bind variables, and result sets.

  5. Dynamic DDL: Used to dynamically execute DDL statements such as CREATE, DROP, ALTER, etc.

  6. Error Handling: Using exceptions and SQLERRM to handle errors in dynamic SQL.

  7. SQL Injection Prevention: Using bind variables to prevent SQL injection attacks.

Conclusion:

Dynamic SQL in Oracle provides the flexibility to construct and execute SQL queries dynamically at runtime, based on changing conditions or user inputs. The key concepts of dynamic SQL — such as EXECUTE IMMEDIATE, bind variables, REF CURSOR, and DBMS_SQL — are essential tools for managing dynamic queries and improving performance, flexibility, and security.

Top comments (0)