Sequences


This tutorial focuses on Oracle 19c Sequences, a powerful database object for generating unique, sequential numbers. Learn how to CREATE, ALTER, and DROP sequences, and effectively use NEXTVAL and CURRVAL to manage unique identifiers in your Oracle Database applications.

 

Sequences: Generating Unique Numbers

Sequences in Oracle 19c are database objects that automatically generate unique numbers. They are commonly used to create primary key values, ensuring each new record has a distinct identifier without manual intervention.

CREATE SEQUENCE

The CREATE SEQUENCE statement is used to define a new sequence object. You can specify various options like starting value, increment, minimum/maximum values, and caching.

Example 1: Basic Sequence Creation

CREATE SEQUENCE emp_id_seq
START WITH 1
INCREMENT BY 1
NOCACHE; -- Creates a sequence named emp_id_seq starting at 1, incrementing by 1, without caching

Explanation This code creates a simple sequence emp_id_seq that generates numbers starting from 1 and increasing by 1 for each call. NOCACHE means values are not pre-allocated in memory.

Example 2: Sequence with Max Value and Cycle

CREATE SEQUENCE order_num_seq
START WITH 100
INCREMENT BY 5
MAXVALUE 1000
CYCLE
NOCACHE; -- Sequence starting at 100, incrementing by 5, cycles after 1000

Explanation This sequence order_num_seq starts at 100, increments by 5, and will cycle back to its start value after reaching 1000, which is useful for limited ranges.

Example 3: Sequence for Negative Numbers

CREATE SEQUENCE neg_val_seq
START WITH -1
INCREMENT BY -1
MINVALUE -100
NOCACHE; -- Creates a sequence that decrements from -1

Explanation This sequence neg_val_seq demonstrates creating a sequence that generates negative numbers, starting at -1 and decrementing by 1.

Example 4: Sequence with Caching

CREATE SEQUENCE product_code_seq
START WITH 1000
INCREMENT BY 10
CACHE 20; -- Caches 20 sequence numbers in memory for faster access

Explanation This sequence product_code_seq uses CACHE 20, which stores 20 pre-generated numbers in memory, improving performance for frequent number generation.

Example 5: Sequence with NOORDER

CREATE SEQUENCE audit_log_id_seq
START WITH 1
INCREMENT BY 1
NOORDER; -- Allows sequence numbers to be generated out of order for performance in RAC environments

Explanation The NOORDER clause for audit_log_id_seq allows sequence numbers to be generated potentially out of order, which can improve performance, especially in Real Application Clusters (RAC).

 

ALTER SEQUENCE

The ALTER SEQUENCE statement modifies an existing sequence's properties without dropping and recreating it. You can change increment, min/max values, or caching settings.

Example 1: Altering Increment By

ALTER SEQUENCE emp_id_seq
INCREMENT BY 2; -- Changes emp_id_seq to increment by 2

Explanation This statement modifies emp_id_seq so that subsequent calls to NEXTVAL will increase the sequence number by 2 instead of 1.

Example 2: Altering Cache Size

ALTER SEQUENCE product_code_seq
CACHE 50; -- Changes the cache size of product_code_seq to 50

Explanation This alters product_code_seq to cache 50 numbers at a time, potentially further improving performance for concurrent requests.

Example 3: Altering Maxvalue and No Cycle

ALTER SEQUENCE order_num_seq
MAXVALUE 2000
NOCYCLE; -- Increases max value and prevents cycling

Explanation This modifies order_num_seq to have a new maximum value of 2000 and disables the CYCLE option, meaning it will stop generating numbers once 2000 is reached.

Example 4: Restarting a Sequence (Conceptual)

-- To "restart" a sequence, you typically drop and recreate it.
-- ALTER SEQUENCE does not have a "RESTART WITH" option.
-- DROP SEQUENCE emp_id_seq;
-- CREATE SEQUENCE emp_id_seq START WITH 1 INCREMENT BY 1 NOCACHE;

Explanation Oracle's ALTER SEQUENCE command does not support resetting the current value directly. To effectively restart a sequence from a specific value, you must drop and then recreate it.

Example 5: Altering MINVALUE (Only if current value allows)

-- ALTER SEQUENCE neg_val_seq MINVALUE -200;
-- This would work only if the current CURRVAL is greater than or equal to -200.
-- If CURRVAL is -50, setting MINVALUE to -200 is fine. If CURRVAL is -150, setting MINVALUE to -100 would fail.

Explanation You can alter MINVALUE for a sequence, but the new minimum must be less than or equal to the current sequence value; otherwise, an error occurs.

 

DROP SEQUENCE

The DROP SEQUENCE statement removes a sequence object from the database. Once dropped, the sequence cannot be used to generate numbers.

Example 1: Dropping a Sequence

DROP SEQUENCE emp_id_seq; -- Removes the emp_id_seq from the database

Explanation This command permanently deletes the emp_id_seq sequence object from the Oracle database.

Example 2: Dropping Non-Existent Sequence (Error)

-- DROP SEQUENCE non_existent_seq;
-- This would result in an ORA-02289: sequence does not exist error.

Explanation Attempting to drop a sequence that does not exist in the database will result in an error.

Example 3: Dropping Multiple Sequences (Separate statements)

DROP SEQUENCE order_num_seq;
DROP SEQUENCE neg_val_seq; -- Each sequence must be dropped individually

Explanation To drop multiple sequences, you must execute a separate DROP SEQUENCE statement for each sequence.

Example 4: Impact on Dependent Objects

-- Dropping a sequence does not automatically remove default values or triggers
-- that might have used it. These references will become invalid.
-- For example, if a table's default used emp_id_seq.NEXTVAL, it would fail after drop.

Explanation Dropping a sequence does not cascade to objects that referenced it; any column default values or triggers that used the dropped sequence will become invalid and fail.

Example 5: Verifying Sequence Drop

SELECT SEQUENCE_NAME FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'EMP_ID_SEQ';
-- After DROP, this query should return no rows.

Explanation This query can be used to verify if a sequence has been successfully dropped by checking its presence in the USER_SEQUENCES data dictionary view.

 

NEXTVAL

NEXTVAL is a pseudocolumn that retrieves the next available number from a specified sequence. Each call to NEXTVAL increments the sequence and returns the new value.

Example 1: Getting Next Value in INSERT

INSERT INTO employees (employee_id, first_name)
VALUES (emp_id_seq.NEXTVAL, 'Alice'); -- Uses the next number from emp_id_seq for employee_id

Explanation This statement inserts a new employee record, using the next unique number generated by emp_id_seq.NEXTVAL for the employee_id.

Example 2: Getting Next Value in SELECT

SELECT emp_id_seq.NEXTVAL FROM DUAL; -- Retrieves the next sequence value from the DUAL table

Explanation This query directly fetches the next value from emp_id_seq using the DUAL pseudotable, which is often used for single-row results.

Example 3: Multiple NEXTVAL in One Statement (Same Value)

SELECT emp_id_seq.NEXTVAL, emp_id_seq.NEXTVAL FROM DUAL; -- Both calls return the *same* next value

Explanation When NEXTVAL is called multiple times within a single SQL statement, it returns the same incremented value for all calls within that statement.

Example 4: Using NEXTVAL in DEFAULT Clause

CREATE TABLE new_products (
    product_id NUMBER DEFAULT product_code_seq.NEXTVAL, -- Automatically assigns next sequence value
    product_name VARCHAR2(100)
);

Explanation This table definition uses product_code_seq.NEXTVAL as the default value for product_id, automatically assigning a unique ID upon insertion if not specified.

Example 5: NEXTVAL and Triggers

-- CREATE OR REPLACE TRIGGER trg_employees_id
-- BEFORE INSERT ON employees
-- FOR EACH ROW
-- BEGIN
--   :NEW.employee_id := emp_id_seq.NEXTVAL;
-- END;
-- /

Explanation This conceptual trigger demonstrates using NEXTVAL to populate a primary key column (employee_id) automatically before a new row is inserted into the employees table.

 

CURRVAL

CURRVAL is a pseudocolumn that retrieves the current value of a sequence for the current session. It can only be used after NEXTVAL has been called for that sequence in the same session.

Example 1: Getting Current Value

-- First, ensure NEXTVAL has been called at least once in the session
SELECT emp_id_seq.NEXTVAL FROM DUAL; -- Call NEXTVAL to initialize CURRVAL
SELECT emp_id_seq.CURRVAL FROM DUAL; -- Retrieves the last value generated by NEXTVAL in this session

Explanation CURRVAL retrieves the most recently generated NEXTVAL for emp_id_seq within the current session. It requires an initial NEXTVAL call.

Example 2: CURRVAL in Insert (After NEXTVAL)

INSERT INTO orders (order_id, customer_id, order_date)
VALUES (order_num_seq.NEXTVAL, 10, SYSDATE);

INSERT INTO order_items (order_id, item_name, quantity)
VALUES (order_num_seq.CURRVAL, 'Laptop', 1); -- Reuses the order_id from the previous insert

Explanation This demonstrates using CURRVAL to insert related records (order items) with the same order_id that was just generated by NEXTVAL for the main order.

Example 3: Error Using CURRVAL Before NEXTVAL

-- SELECT order_num_seq.CURRVAL FROM DUAL;
-- This would result in ORA-08002: sequence ORDER_NUM_SEQ.CURRVAL is not yet defined in this session.

Explanation Attempting to use CURRVAL before any NEXTVAL call for that sequence in the current session will result in an ORA-08002 error.

Example 4: CURRVAL in a View

CREATE VIEW current_emp_seq AS
SELECT emp_id_seq.CURRVAL AS current_employee_id
FROM DUAL;

Explanation This creates a view that can be queried to see the current value of emp_id_seq within the session, provided NEXTVAL has been called.

Example 5: CURRVAL in Package Variable (Conceptual)

-- PACKAGE my_pkg IS
--   PROCEDURE get_next_and_current(p_next OUT NUMBER, p_curr OUT NUMBER);
-- END my_pkg;
-- PACKAGE BODY my_pkg IS
--   PROCEDURE get_next_and_current(p_next OUT NUMBER, p_curr OUT NUMBER) IS
--   BEGIN
--     p_next := emp_id_seq.NEXTVAL;
--     p_curr := emp_id_seq.CURRVAL;
--   END;
-- END my_pkg;

Explanation This conceptual PL/SQL package demonstrates how NEXTVAL and CURRVAL can be used within procedural code to retrieve and manage sequence values.