Introduction

Oracle APEX applications often require efficient search functionality. However, traditional SQL LIKE searches do not handle typos or similar words effectively.

A fuzzy search can improve search accuracy by finding similar words based on string matching techniques. Oracle provides the UTL_MATCH package, which allows comparison between words using:
EDIT_DISTANCE – Measures the number of changes required to convert one word into another.
EDIT_DISTANCE_SIMILARITY – Returns similarity as a percentage (0-100).
JARO_WINKLER_SIMILARITY – Compares strings based on common prefixes and transpositions.

This post will demonstrate how to implement a fuzzy search using UTL_MATCH in Oracle APEX.

Why Use Fuzzy Search?

  • Handles typos (e.g., “Jon” vs. “John”).
  • Finds similar names or products (e.g., “Alexandra” vs. “Aleksandra”).
  • Improves user experience by ranking search results based on similarity.

Step 1: Create a Sample Table

We will create a sample customer table for testing fuzzy search queries.

CREATE TABLE customers (
    id          NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    first_name  VARCHAR2(50),
    last_name   VARCHAR2(50),
    full_name   VARCHAR2(100) GENERATED ALWAYS AS (first_name || ' ' || last_name) VIRTUAL
);

Using a virtual column ( full_name ) ensures consistent searching without storing redundant data.

Insert some sample records:

INSERT INTO customers (first_name, last_name) VALUES ('John', 'Doe');
INSERT INTO customers (first_name, last_name) VALUES ('Jon', 'Doh');
INSERT INTO customers (first_name, last_name) VALUES ('Jane', 'Smith');
INSERT INTO customers (first_name, last_name) VALUES ('Janet', 'Smyth');
COMMIT;

Step 2: Fuzzy Search Query Using UTL_MATCH

We will use UTL_MATCH.EDIT_DISTANCE_SIMILARITY to rank similar names.

SELECT id, first_name, last_name,
       UTL_MATCH.EDIT_DISTANCE_SIMILARITY(full_name, 'Jon Doe') AS similarity_score
FROM customers
ORDER BY similarity_score DESC;

This query compares the full_name column against “Jon Doe” and returns a similarity score.

Example Output:

ID First Name Last Name Similarity Score
1 John Doe 95
2 Jon Doh 90
3 Jane Smith 40
4 Janet Smyth

Step 3: Creating a Fuzzy Search Function in PL/SQL

To use fuzzy search in APEX Interactive Reports or Dynamic Actions, create a function:

CREATE OR REPLACE FUNCTION fuzzy_search(p_search VARCHAR2)
RETURN SYS_REFCURSOR
AS
    v_cursor SYS_REFCURSOR;
BEGIN
    OPEN v_cursor FOR
    SELECT id, first_name, last_name,
           UTL_MATCH.EDIT_DISTANCE_SIMILARITY(full_name, p_search) AS similarity_score
    FROM customers
    WHERE UTL_MATCH.EDIT_DISTANCE_SIMILARITY(full_name, p_search) > 50  -- Filter weak matches
    ORDER BY similarity_score DESC;

    RETURN v_cursor;
END fuzzy_search;

This function returns customers with at least 50% similarity to the search term.

Step 4: Using Fuzzy Search in an APEX Report

Create a Search Page in APEX

  • Add a Text Field (P1_SEARCH_NAME) for user input.
  • Add an Interactive Report on the CUSTOMERS table.

Modify Report Query

Set the SQL Query of the report to:

SELECT id, first_name, last_name,
       UTL_MATCH.EDIT_DISTANCE_SIMILARITY(full_name, :P1_SEARCH_NAME) AS similarity_score
FROM customers
WHERE UTL_MATCH.EDIT_DISTANCE_SIMILARITY(full_name, :P1_SEARCH_NAME) > 50
ORDER BY similarity_score DESC;

The report dynamically filters and ranks similar names.

Step 5: Using a PL/SQL Dynamic Action for Real-Time Search

Instead of reloading the page, use a Dynamic Action for real-time search.

Create a Dynamic Action

  • Event: Key Release
  • Selection Type: Item
  • Item: P1_SEARCH_NAME
  • Action: Execute PL/SQL Code
  • Code:
DECLARE
    v_cursor SYS_REFCURSOR;
BEGIN
    v_cursor := fuzzy_search(:P1_SEARCH_NAME);
    APEX_UTIL.OPEN_CACHED_QUERY(v_cursor);
END;
  • Affected Elements: Interactive Report (Refresh after execution).

This enables instant fuzzy search as the user types.

Step 6: Enhancing Search with JARO_WINKLER_SIMILARITY

The Jaro-Winkler Similarity algorithm is useful for short names or misspellings.

Modify the query:

SELECT id, first_name, last_name,
       UTL_MATCH.JARO_WINKLER_SIMILARITY(full_name, :P1_SEARCH_NAME) AS similarity_score
FROM customers
WHERE UTL_MATCH.JARO_WINKLER_SIMILARITY(full_name, :P1_SEARCH_NAME) > 80
ORDER BY similarity_score DESC;

Jaro-Winkler gives higher weight to common prefixes, making it ideal for name searches.


Conclusion

UTL_MATCH provides a powerful way to implement fuzzy search in Oracle APEX.

Key Benefits:
✔ Handles misspellings and typos.
✔ Ranks results based on similarity score.
✔ Works with Interactive Reports and Dynamic Actions for instant search.
✔ Supports multiple algorithms (EDIT_DISTANCE, JARO_WINKLER).

Recommended Posts

Start typing and press Enter to search