Skip to main content

What is Filtering Data?

Filtering Data is the process of retrieving a subset of rows from a database table based on specific conditions. In SQL, this is primarily accomplished using the WHERE clause in a SELECT, UPDATE, or DELETE statement. Its core purpose is to pinpoint and manipulate only the relevant data, effectively solving the problem of information overload by excluding irrelevant records.
Filtering is fundamental to achieving precision and efficiency in data retrieval and manipulation.

Comparison Operators

Comparison operators form the bedrock of filtering conditions (=, != or <>, <, >, <=, >=).
DECLARE
  l_employee_name employees.last_name%TYPE;
BEGIN
  -- Select the employee whose ID is exactly 100
  SELECT last_name INTO l_employee_name
  FROM employees
  WHERE employee_id = 100; -- Using the equality operator '='

  DBMS_OUTPUT.PUT_LINE('Employee Name: ' || l_employee_name);
END;
/

Logical Operators AND

The AND operator is used to combine multiple conditions where all must be true for a row to be included.
The AND operator narrows the result set, making the filter more specific.
BEGIN
  -- Update salary for employees in a specific department who have a specific job title
  UPDATE employees
  SET salary = salary * 1.10 -- 10% raise
  WHERE department_id = 60
    AND job_id = 'IT_PROG'; -- Both conditions MUST be true
  DBMS_OUTPUT.PUT_LINE('Salaries updated for IT Programmers in Dept 60: ' || SQL%ROWCOUNT);
END;
/

Logical Operators OR

The OR operator combines multiple conditions where at least one must be true for a row to be included.
DECLARE
  CURSOR emp_cur IS
    -- Select employees who are either Managers or based in location 1700
    SELECT first_name, last_name, job_id, department_id
    FROM employees
    WHERE job_id LIKE '%MAN' -- Condition 1: Job is a Manager
       OR department_id IN (SELECT department_id 
                           FROM departments 
                           WHERE location_id = 1700); -- Condition 2: In location 1700
BEGIN
  FOR emp_rec IN emp_cur LOOP
    DBMS_OUTPUT.PUT_LINE(emp_rec.last_name || ' works as ' || emp_rec.job_id);
  END LOOP;
END;
/

NOT Operator

A logical operator that negates a condition. It returns TRUE if the condition following it is FALSE.
The NOT operator is powerful but should be used judiciously as it can sometimes hinder performance.
BEGIN
  -- Delete employees who are NOT in the 'IT' department
  DELETE FROM employees
  WHERE NOT (department_id = 60); -- Negates the condition "department_id = 60"

  DBMS_OUTPUT.PUT_LINE('Employees not in IT deleted: ' || SQL%ROWCOUNT);
END;
/

IN Operator

Provides a concise way to check if a value matches any value in a list.
The IN operator is a shorthand for multiple OR conditions and improves code readability.
DECLARE
  CURSOR c_managers IS
    -- Select employees whose manager ID is in a specific list
    SELECT first_name, last_name
    FROM employees
    WHERE manager_id IN (100, 102, 114); -- Equivalent to manager_id=100 OR manager_id=102 OR manager_id=114
BEGIN
  FOR rec IN c_managers LOOP
    DBMS_OUTPUT.PUT_LINE('Managed by senior staff: ' || rec.first_name || ' ' || rec.last_name);
  END LOOP;
END;
/

BETWEEN Operator

Used to filter a range of values (inclusive). It checks if a value is within a specified lower and upper bound.
BEGIN
  -- Select employees hired between two specific dates
  FOR rec IN (
    SELECT first_name, hire_date
    FROM employees
    WHERE hire_date BETWEEN DATE '2003-01-01' AND DATE '2003-12-31' -- Inclusive range for the year 2003
  ) LOOP
    DBMS_OUTPUT.PUT_LINE(rec.first_name || ' was hired in 2003 on ' || rec.hire_date);
  END LOOP;
END;
/

LIKE Operator

Used for pattern matching on string data using wildcards:
  • % matches any sequence of characters (zero or more)
  • _ matches exactly one character
DECLARE
  v_search_pattern VARCHAR2(20) := 'S%';
BEGIN
  -- Find all employees whose last name starts with 'S'
  FOR rec IN (
    SELECT last_name
    FROM employees
    WHERE UPPER(last_name) LIKE v_search_pattern -- The '%' wildcard matches any characters after 'S'
  ) LOOP
    DBMS_OUTPUT.PUT_LINE('Found: ' || rec.last_name);
  END LOOP;
END;
/

IS NULL Operator

Specifically used to check for NULL values.
A common mistake is using = NULL, which always evaluates to UNKNOWN. Always use IS NULL or IS NOT NULL.
BEGIN
  -- Update records where the commission percentage has not been set (is NULL)
  UPDATE employees
  SET commission_pct = 0
  WHERE commission_pct IS NULL; -- Correctly identifies rows with NULL values

  DBMS_OUTPUT.PUT_LINE('Updated ' || SQL%ROWCOUNT || ' rows with NULL commission.');
END;
/

Why is Filtering Data Important?

Performance & Scalability

By filtering data at the source (in the database), you minimize the amount of data transferred to the PL/SQL engine and client, adhering to the principle of Set-Based Processing. This is far more scalable than fetching entire tables and filtering procedurally.

Data Integrity & Accuracy

Precise filtering, especially in UPDATE and DELETE statements, prevents unintended changes to data. This ensures ACID compliance by guaranteeing that transactions only affect the correct rows, maintaining database integrity.

Code Maintainability (DRY)

By embedding the filtering logic directly in the SQL statement, you avoid writing verbose procedural code (e.g., loops with IF statements) to sift through data. This keeps code DRY (Don’t Repeat Yourself) and more declarative.

Advanced Nuances

Operator Precedence and Parentheses

Logical operators have a defined precedence: NOT, AND, then OR. Use parentheses to clarify ambiguous conditions.
-- Without parentheses (ambiguous)
WHERE condition1 OR condition2 AND condition3
-- Evaluated as: condition1 OR (condition2 AND condition3)

-- With parentheses (explicit)
WHERE (condition1 OR condition2) AND condition3

LIKE with Escaped Characters

When searching for strings containing literal % or _ characters, use the ESCAPE clause:
WHERE file_name LIKE '%\_backup%' ESCAPE '\'

BETWEEN with Dates and Timestamps

While BETWEEN is inclusive, it can be tricky with TIMESTAMP data types. Use careful range definitions.
-- Common pattern to exclude upper bound
WHERE timestamp_col >= start_date AND timestamp_col < end_date + 1

How This Fits the Roadmap

Within the “Basic SQL Querying” section, Filtering Data is a foundational pillar.

Immediate Prerequisites For:

  • Data Aggregation (GROUP BY, HAVING) - You must filter individual rows before grouping
  • Joining Tables - The ON clause is itself a filter, and WHERE filters join results

Essential For Advanced Topics:

  • Cursor Design - Efficient cursors rely on well-filtered result sets
  • Dynamic SQL - Building WHERE clauses dynamically based on user input
  • Performance Tuning - The effectiveness of indexes depends on efficient WHERE clauses
Precise data filtering is not a “basic” skill to be forgotten but a core competency that underpins all efficient and correct database programming.

Build docs developers (and LLMs) love