DEV Community

Pranav Bakare
Pranav Bakare

Posted on

PLSQL BEST PART 1

Detailed explanation of the questions and answers provided earlier, along with examples to illustrate how each concept works in Oracle PL/SQL:


  1. Triggers in PL/SQL

Explanation: Triggers are special stored procedures in PL/SQL that are automatically executed (or "triggered") when certain events occur on a database table or view. There are two main types of triggers in PL/SQL: Row-Level Triggers and Statement-Level Triggers.

Row-Level Triggers: Fired once for each row affected by the triggering statement.

Statement-Level Triggers: Fired once for the entire SQL statement, regardless of how many rows are affected.

Example:

Row-Level Trigger: This trigger is executed after every row update on the employees table.

CREATE OR REPLACE TRIGGER log_employee_updates

AFTER UPDATE ON employees

FOR EACH ROW

BEGIN

INSERT INTO audit_table (old_salary, new_salary, change_date)

VALUES (:OLD.salary, :NEW.salary, SYSDATE);

END;

Statement-Level Trigger: This trigger prevents bulk deletion if there are more than 10 rows in the employees table.

CREATE OR REPLACE TRIGGER prevent_bulk_delete

BEFORE DELETE ON employees

BEGIN

IF (SELECT COUNT(*) FROM employees) > 10 THEN

RAISE_APPLICATION_ERROR(-20001, 'Bulk delete is not allowed.');

END IF;

END;


  1. Compound Triggers

Explanation: A Compound Trigger is a single trigger that combines multiple triggering actions (e.g., BEFORE, AFTER) into one block. It is useful for consolidating logic and preventing mutating table errors, which can occur when a trigger tries to modify the table that caused the trigger to fire.

Example:

CREATE OR REPLACE TRIGGER emp_audit_trigger

FOR INSERT OR UPDATE ON employees

COMPOUND TRIGGER

TYPE emp_changes IS TABLE OF employees%ROWTYPE;

emp_log emp_changes := emp_changes();

BEFORE EACH ROW IS  
BEGIN  
    emp_log.EXTEND;  
    emp_log(emp_log.COUNT) := :NEW;  
END BEFORE EACH ROW;  

AFTER STATEMENT IS  
BEGIN  
    FORALL i IN emp_log.FIRST..emp_log.LAST  
        INSERT INTO audit_table VALUES emp_log(i);  
END AFTER STATEMENT;  
Enter fullscreen mode Exit fullscreen mode

END;

The BEFORE EACH ROW section captures the new row data.

The AFTER STATEMENT section processes the data and inserts it into the audit_table.


  1. Bind Variables in SQL

Explanation: Bind variables are placeholders used in SQL queries to allow the reuse of SQL execution plans, improving performance and security. They prevent SQL injection and reduce the overhead of SQL parsing.

Example:

DECLARE

emp_id NUMBER := 101;

emp_name VARCHAR2(50);

BEGIN

SELECT first_name INTO emp_name FROM employees WHERE employee_id = :emp_id;

DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_name);

END;

:emp_id is a bind variable that is substituted at runtime. It allows Oracle to cache the execution plan, reducing parsing overhead.


  1. Error Handling in PL/SQL

Explanation: In PL/SQL, error handling is done using the EXCEPTION block. You can handle multiple exceptions to manage different types of errors in your code.

Example:

DECLARE

v_salary employees.salary%TYPE;

BEGIN

SELECT salary INTO v_salary FROM employees WHERE employee_id = 999;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('No data found for the given employee ID.');

WHEN TOO_MANY_ROWS THEN

DBMS_OUTPUT.PUT_LINE('Multiple rows found for the query.');

WHEN OTHERS THEN

DBMS_OUTPUT.PUT_LINE('An unexpected error occurred: ' || SQLERRM);

END;

NO_DATA_FOUND is triggered when no rows match the query.

TOO_MANY_ROWS is triggered when more than one row is returned by the query.

OTHERS is a catch-all exception that handles any unexpected errors.


  1. Auditing Changes to Tables Using Triggers

Explanation: Auditing refers to tracking changes (like insertions, updates, or deletions) to sensitive tables. You can implement auditing using triggers to log such changes in an audit table.

Example:

CREATE OR REPLACE TRIGGER track_changes

AFTER INSERT OR UPDATE OR DELETE ON sensitive_table

FOR EACH ROW

BEGIN

IF INSERTING THEN

INSERT INTO audit_table (action, table_name, timestamp)

VALUES ('INSERT', 'sensitive_table', SYSDATE);

ELSIF UPDATING THEN

INSERT INTO audit_table (action, table_name, timestamp)

VALUES ('UPDATE', 'sensitive_table', SYSDATE);

ELSIF DELETING THEN

INSERT INTO audit_table (action, table_name, timestamp)

VALUES ('DELETE', 'sensitive_table', SYSDATE);

END IF;

END;

This trigger logs the action (insert, update, or delete) and the timestamp whenever a change occurs on sensitive_table.


  1. Partitioning in PL/SQL

Explanation: Partitioning divides a large table into smaller, more manageable pieces called partitions. This improves query performance by allowing Oracle to scan only the relevant partitions, rather than the entire table.

Example:

CREATE TABLE sales (

sale_id NUMBER,

sale_date DATE,

amount NUMBER

) PARTITION BY RANGE (sale_date) (

PARTITION p1 VALUES LESS THAN (TO_DATE('2023-01-01', 'YYYY-MM-DD')),

PARTITION p2 VALUES LESS THAN (TO_DATE('2024-01-01', 'YYYY-MM-DD'))

);

p1 holds sales before 2023-01-01, and p2 holds sales before 2024-01-01.

Queries can be optimized by targeting the relevant partition.


  1. MERGE Statement (Upserts)

Explanation: The MERGE statement allows you to perform an upsert (update if the record exists, insert if it doesn't). It's a powerful SQL statement for handling conditional updates or inserts.

Example:

MERGE INTO employees tgt

USING (SELECT 105 AS employee_id, 'Jane' AS first_name, 5000 AS salary FROM DUAL) src

ON (tgt.employee_id = src.employee_id)

WHEN MATCHED THEN

UPDATE SET tgt.salary = src.salary

WHEN NOT MATCHED THEN

INSERT (employee_id, first_name, salary)

VALUES (src.employee_id, src.first_name, src.salary);

If employee_id = 105 exists, the salary is updated.

If employee_id = 105 does not exist, a new row is inserted.


  1. Pipelined Functions

Explanation: A pipelined function returns a set of rows that can be processed as if it were a table. It's often used for performance optimization in scenarios where large datasets need to be processed in a pipelined manner.

Example:

CREATE OR REPLACE FUNCTION get_numbers RETURN SYS.ODCINUMBERLIST PIPELINED IS

BEGIN

FOR i IN 1..10 LOOP

PIPE ROW(i);

END LOOP;

END;

/

SELECT * FROM TABLE(get_numbers);

This function generates numbers from 1 to 10 and pipes them as rows, which can be queried like a table.


These explanations and examples should provide you with a comprehensive understanding of the PL/SQL concepts and how to implement them. Let me know if you need further clarification!

Top comments (0)