BEFORE INSERT Trigger

An Oracle BEFORE INSERT Trigger is a type of trigger that fires before an INSERT statement is executed on a table. It is commonly used to validate, manipulate, or assign values to rows before they are inserted into the table. It allows you to modify the data being inserted, perform checks, and take other actions before the actual insertion occurs. Here's a detailed explanation:

1. Basic Structure of a BEFORE INSERT Trigger

CREATE OR REPLACE TRIGGER trigger_name

BEFORE INSERT ON table_name

FOR EACH ROW

BEGIN

  -- Trigger logic goes here

END;

Key Components:

  • BEFORE INSERT: This specifies that the trigger will fire before the insert operation on the target table.
  • FOR EACH ROW: This means the trigger will fire once for each row being inserted into the table. Each row can have its own logic applied.
  • BEGIN ... END;: Contains the PL/SQL block of code that will be executed when the trigger fires.

2. Common Use Cases for BEFORE INSERT Triggers

a. Data Validation

You can perform checks to ensure that the data being inserted meets specific business rules. For example:

  • Enforcing non-null constraints.
  • Checking for valid values in a column.
  • Ensuring foreign key constraints are met (even before insertion).

CREATE OR REPLACE TRIGGER check_valid_data

BEFORE INSERT ON employees

FOR EACH ROW

BEGIN

  IF :NEW.salary < 1000 THEN

    RAISE_APPLICATION_ERROR(-20001, 'Salary must be at least 1000');

  END IF;

END;

Here, if the salary being inserted is less than 1000, an error is raised.

b. Default Value Assignment

You can assign default values to columns if no value is provided in the INSERT statement. This is commonly used for auditing purposes or to set system-related values, such as timestamps or user identifiers.

CREATE OR REPLACE TRIGGER set_default_values

BEFORE INSERT ON orders

FOR EACH ROW

BEGIN

  IF :NEW.order_date IS NULL THEN

    :NEW.order_date := SYSDATE; -- Default to the current date

  END IF;

  IF :NEW.status IS NULL THEN

    :NEW.status := 'PENDING'; -- Default order status

  END IF;

END;

In this case, if the order_date or status is not provided, the trigger will set them to the current date and a default status of "PENDING".

c. Timestamping / Audit Logging

It is common to capture timestamps or user details for auditing purposes. For instance, you can automatically set a created_at timestamp before inserting the row into the table.

CREATE OR REPLACE TRIGGER set_creation_timestamp

BEFORE INSERT ON employees

FOR EACH ROW

BEGIN

  :NEW.created_at := SYSDATE; -- Automatically set timestamp

  :NEW.created_by := USER;    -- Set the user who created the record

END;

In this example, the trigger automatically sets the created_at and created_by fields to the current date and the current Oracle user, respectively.

3. Accessing Data in BEFORE INSERT Trigger

Within a BEFORE INSERT trigger, you use the :NEW pseudo-record to reference the values that will be inserted into the table. This allows you to:

  • Modify the data before it is inserted.
  • Access the data for validation or processing.

Example of modifying data before insertion:

CREATE OR REPLACE TRIGGER modify_email

BEFORE INSERT ON users

FOR EACH ROW

BEGIN

  :NEW.email := LOWER(:NEW.email);  -- Converts the email to lowercase before insertion

END;

Here, the :NEW.email value is modified to be lowercase before the insert operation is performed.

4. NEW vs OLD References

  • :NEW: Refers to the values that are being inserted into the table. It is used to access and manipulate the data before it is written to the database.
  • :OLD: In the case of UPDATE and DELETE triggers, the :OLD pseudo-record holds the values before the modification (not applicable for INSERT triggers, since there is no existing value to reference).

In BEFORE INSERT triggers, you'll generally only interact with :NEW since you're inserting new data, not modifying existing data.

5. Row-Level vs Statement-Level Triggers

  • Row-Level Trigger (FOR EACH ROW): This type of trigger fires once for each row being inserted. This is the most common type of trigger used for BEFORE INSERT.
  • Statement-Level Trigger: A statement-level trigger fires once for the entire SQL statement, regardless of how many rows are being inserted.

Example of a statement-level trigger:

CREATE OR REPLACE TRIGGER stmt_level_trigger

BEFORE INSERT ON employees

BEGIN

  DBMS_OUTPUT.PUT_LINE('Inserting data into employees table');

END;

This would fire just once, before the INSERT statement, regardless of how many rows are inserted.

6. Trigger Restrictions

  • DML operations within a trigger: While you can modify the data within a BEFORE INSERT trigger (via :NEW), performing DML operations such as INSERT, UPDATE, or DELETE within a trigger can be tricky and often results in an error due to recursion or unintentional side effects. In general, you should avoid DML operations within a BEFORE INSERT trigger unless absolutely necessary.
  • Mutating Table Error: This error occurs when a trigger tries to modify or query the table that is causing the trigger to fire. Oracle doesn’t allow this to prevent logical errors or infinite loops.

7. Error Handling in BEFORE INSERT Triggers

If you want to prevent the insert from occurring based on certain conditions, you can use the RAISE_APPLICATION_ERROR function to generate an error. This will stop the INSERT operation.

CREATE OR REPLACE TRIGGER prevent_negative_salary

BEFORE INSERT ON employees

FOR EACH ROW

BEGIN

  IF :NEW.salary < 0 THEN

    RAISE_APPLICATION_ERROR(-20001, 'Salary cannot be negative');

  END IF;

END;

If the salary is negative, an error will be raised, and the insert will be aborted.

8. Advantages of Using BEFORE INSERT Triggers

  • Data Integrity: Helps ensure the data meets business rules before it's even inserted into the table.
  • Automated Auditing: Can automatically log system data, like timestamps or user IDs, without relying on the application code.
  • Centralized Logic: By enforcing rules within the database, you can centralize business logic rather than having it duplicated in each application that interacts with the database.

9. Disabling and Dropping a Trigger

If needed, you can disable a trigger temporarily or drop it entirely.

  • Disabling a Trigger:

·        ALTER TRIGGER trigger_name DISABLE;

  • Dropping a Trigger:

·        DROP TRIGGER trigger_name;

Disabling a trigger can be useful during bulk data operations where you don't want the trigger to fire.

No comments:

Post a Comment