ORA-06502 PL/SQL Numeric or Value Error - Complete Resolution Guide
ORA-06502: PL/SQL: Numeric or Value Error
Section titled “ORA-06502: PL/SQL: Numeric or Value Error”Error Overview
Section titled “Error Overview”Error Text: ORA-06502: PL/SQL: numeric or value error
The ORA-06502 error is one of the most common PL/SQL runtime errors. It occurs when a value assignment or conversion violates datatype constraints. This error has many variations indicating the specific cause, such as character string buffer too small, number precision too large, or character to number conversion error.
Common Error Variations
Section titled “Common Error Variations”| Variation | Description |
|---|---|
character string buffer too small | Value exceeds VARCHAR2 variable length |
number precision too large | Number exceeds defined precision |
character to number conversion error | Invalid string-to-number conversion |
null index table key value | NULL used as associative array index |
bulk bind: truncated bind | Bulk operation data truncation |
Common Causes
Section titled “Common Causes”1. String Buffer Overflow
Section titled “1. String Buffer Overflow”- Assigning value longer than variable definition
- Concatenation result exceeds buffer
- Substring operations returning unexpected lengths
2. Number Precision Issues
Section titled “2. Number Precision Issues”- Value exceeds NUMBER precision
- Scale overflow during calculations
- Division results with too many decimal places
3. Type Conversion Failures
Section titled “3. Type Conversion Failures”- Non-numeric string to NUMBER conversion
- Invalid date string formats
- Implicit conversion failures
4. NULL Value Handling
Section titled “4. NULL Value Handling”- NULL in arithmetic operations
- NULL as collection index
- Uninitialized variable usage
Diagnostic Examples
Section titled “Diagnostic Examples”Scenario 1: Character String Buffer Too Small
Section titled “Scenario 1: Character String Buffer Too Small”-- ERROR: Buffer overflowDECLARE v_name VARCHAR2(10);BEGIN v_name := 'This is a very long string'; -- 26 charactersEND;/-- ORA-06502: PL/SQL: numeric or value error: character string buffer too small
-- SOLUTION 1: Increase buffer sizeDECLARE v_name VARCHAR2(100);BEGIN v_name := 'This is a very long string';END;/
-- SOLUTION 2: Use SUBSTR to truncateDECLARE v_name VARCHAR2(10);BEGIN v_name := SUBSTR('This is a very long string', 1, 10);END;/
-- SOLUTION 3: Use %TYPE for column-based sizingDECLARE v_name employees.last_name%TYPE; -- Inherits column sizeBEGIN SELECT last_name INTO v_name FROM employees WHERE employee_id = 100;END;/Scenario 2: Number Precision Too Large
Section titled “Scenario 2: Number Precision Too Large”-- ERROR: Precision overflowDECLARE v_num NUMBER(5,2); -- Max: 999.99BEGIN v_num := 12345.67; -- Too largeEND;/-- ORA-06502: PL/SQL: numeric or value error: number precision too large
-- SOLUTION 1: Increase precisionDECLARE v_num NUMBER(10,2);BEGIN v_num := 12345.67;END;/
-- SOLUTION 2: Use ROUND to fit precisionDECLARE v_num NUMBER(5,2);BEGIN v_num := ROUND(123.456789, 2); -- Results in 123.46END;/
-- SOLUTION 3: Use TRUNC for truncation without roundingDECLARE v_num NUMBER(5,2);BEGIN v_num := TRUNC(123.456789, 2); -- Results in 123.45END;/Scenario 3: Character to Number Conversion Error
Section titled “Scenario 3: Character to Number Conversion Error”-- ERROR: Invalid number conversionDECLARE v_num NUMBER;BEGIN v_num := TO_NUMBER('ABC123');END;/-- ORA-06502: PL/SQL: numeric or value error: character to number conversion error
-- SOLUTION 1: Validate before conversionDECLARE v_num NUMBER; v_str VARCHAR2(20) := 'ABC123';BEGIN -- Check if string is numeric IF REGEXP_LIKE(v_str, '^\d+\.?\d*$') THEN v_num := TO_NUMBER(v_str); ELSE v_num := NULL; -- Or handle error DBMS_OUTPUT.PUT_LINE('Invalid number format: ' || v_str); END IF;END;/
-- SOLUTION 2: Use exception handlingDECLARE v_num NUMBER;BEGIN BEGIN v_num := TO_NUMBER('ABC123'); EXCEPTION WHEN VALUE_ERROR THEN v_num := 0; -- Default value DBMS_OUTPUT.PUT_LINE('Conversion failed, using default'); END;END;/
-- SOLUTION 3: Extract numeric portionDECLARE v_num NUMBER; v_str VARCHAR2(20) := 'ABC123';BEGIN v_num := TO_NUMBER(REGEXP_REPLACE(v_str, '[^0-9.]', '')); DBMS_OUTPUT.PUT_LINE('Extracted number: ' || v_num); -- 123END;/Scenario 4: NULL Index in Associative Array
Section titled “Scenario 4: NULL Index in Associative Array”-- ERROR: NULL indexDECLARE TYPE t_lookup IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(50); v_lookup t_lookup; v_key VARCHAR2(50);BEGIN v_key := NULL; v_lookup(v_key) := 'test'; -- NULL key not allowedEND;/-- ORA-06502: PL/SQL: numeric or value error: NULL index table key value
-- SOLUTION: Validate key before useDECLARE TYPE t_lookup IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(50); v_lookup t_lookup; v_key VARCHAR2(50);BEGIN v_key := NULL; IF v_key IS NOT NULL THEN v_lookup(v_key) := 'test'; ELSE DBMS_OUTPUT.PUT_LINE('Cannot use NULL as key'); END IF;END;/Scenario 5: Bulk Bind Truncation
Section titled “Scenario 5: Bulk Bind Truncation”-- ERROR: Bulk bind truncationDECLARE TYPE t_names IS TABLE OF VARCHAR2(10); v_names t_names;BEGIN SELECT last_name BULK COLLECT INTO v_names FROM employees; -- Some names > 10 charsEND;/-- ORA-06502: PL/SQL: numeric or value error: bulk bind: truncated bind
-- SOLUTION: Use appropriate size or %TYPEDECLARE TYPE t_names IS TABLE OF employees.last_name%TYPE; v_names t_names;BEGIN SELECT last_name BULK COLLECT INTO v_names FROM employees;END;/Diagnostic Queries
Section titled “Diagnostic Queries”Find Column Sizes for %TYPE Usage
Section titled “Find Column Sizes for %TYPE Usage”-- Check column definitions for proper variable sizingSELECT column_name, data_type, data_length, data_precision, data_scale, nullableFROM all_tab_columnsWHERE owner = 'HR' AND table_name = 'EMPLOYEES'ORDER BY column_id;Identify Potential Overflow Data
Section titled “Identify Potential Overflow Data”-- Find values that would cause overflow-- Example: Find names longer than 10 charactersSELECT employee_id, last_name, LENGTH(last_name) as name_lengthFROM employeesWHERE LENGTH(last_name) > 10;
-- Find numbers that exceed precisionSELECT *FROM transactionsWHERE amount >= 1000000 -- Would overflow NUMBER(8,2) OR amount < -1000000;Check PL/SQL Code for Issues
Section titled “Check PL/SQL Code for Issues”-- Find PL/SQL objects with potential issuesSELECT owner, name, type, line, textFROM all_sourceWHERE REGEXP_LIKE(text, 'VARCHAR2\s*\(\s*[1-9]\s*\)', 'i') -- Small buffers AND owner = 'SCHEMA_NAME'ORDER BY name, line;
-- Find hardcoded small number precisionSELECT owner, name, type, line, textFROM all_sourceWHERE REGEXP_LIKE(text, 'NUMBER\s*\(\s*[1-3]\s*(,|\))', 'i') AND owner = 'SCHEMA_NAME'ORDER BY name, line;Resolution Strategies
Section titled “Resolution Strategies”1. Defensive Variable Declaration
Section titled “1. Defensive Variable Declaration”-- Use maximum practical sizesDECLARE v_name VARCHAR2(4000); -- Max VARCHAR2 in PL/SQL v_clob CLOB; -- For unlimited text v_num NUMBER; -- Unrestricted precision
-- Better: Use %TYPE for database columns v_emp_name employees.last_name%TYPE; v_salary employees.salary%TYPE;
-- Use %ROWTYPE for entire rows v_emp_rec employees%ROWTYPE;BEGIN -- Safe from buffer overflow SELECT last_name, salary INTO v_emp_name, v_salary FROM employees WHERE employee_id = 100;END;/2. Safe Type Conversion Functions
Section titled “2. Safe Type Conversion Functions”-- Create safe conversion functionCREATE OR REPLACE FUNCTION safe_to_number( p_str IN VARCHAR2, p_default IN NUMBER DEFAULT NULL) RETURN NUMBER ISBEGIN RETURN TO_NUMBER(p_str);EXCEPTION WHEN VALUE_ERROR THEN RETURN p_default;END safe_to_number;/
-- UsageDECLARE v_num NUMBER;BEGIN v_num := safe_to_number('ABC', 0); -- Returns 0 v_num := safe_to_number('123', 0); -- Returns 123END;/3. Validation Before Assignment
Section titled “3. Validation Before Assignment”-- Validate string length before assignmentCREATE OR REPLACE FUNCTION safe_assign( p_value IN VARCHAR2, p_max_len IN NUMBER) RETURN VARCHAR2 ISBEGIN IF p_value IS NULL THEN RETURN NULL; ELSIF LENGTH(p_value) > p_max_len THEN RETURN SUBSTR(p_value, 1, p_max_len); ELSE RETURN p_value; END IF;END safe_assign;/
-- UsageDECLARE v_short VARCHAR2(10);BEGIN v_short := safe_assign('This is a very long string', 10); -- v_short = 'This is a 'END;/4. Exception Handling Pattern
Section titled “4. Exception Handling Pattern”DECLARE v_result VARCHAR2(100);BEGIN -- Wrap risky operations BEGIN -- Potentially dangerous operation v_result := some_function_that_might_overflow(); EXCEPTION WHEN VALUE_ERROR THEN -- Log the error INSERT INTO error_log (error_date, error_msg) VALUES (SYSDATE, 'Value error in some_function'); COMMIT; -- Set safe default v_result := 'ERROR'; END;
-- Continue processing DBMS_OUTPUT.PUT_LINE('Result: ' || v_result);END;/Prevention Best Practices
Section titled “Prevention Best Practices”1. Variable Declaration Guidelines
Section titled “1. Variable Declaration Guidelines”-- GOOD: Use %TYPE for column-based variablesv_name employees.last_name%TYPE;
-- GOOD: Use generous sizes for computed valuesv_full_name VARCHAR2(500); -- first || ' ' || last || ' ' || suffix
-- GOOD: Use NUMBER without precision for calculationsv_result NUMBER;
-- BAD: Hardcoded small sizesv_name VARCHAR2(10); -- Too small!
-- BAD: Tight precision for calculationsv_result NUMBER(5,2); -- May overflow2. Safe String Concatenation
Section titled “2. Safe String Concatenation”DECLARE v_result VARCHAR2(4000); v_first VARCHAR2(100) := 'John'; v_last VARCHAR2(100) := 'Doe';BEGIN -- Safe concatenation with NULL handling v_result := NVL(v_first, '') || ' ' || NVL(v_last, '');
-- Or use CONCAT (auto-handles NULL) v_result := v_first || ' ' || v_last;END;/3. Number Calculation Safety
Section titled “3. Number Calculation Safety”DECLARE v_result NUMBER; v_divisor NUMBER := 0;BEGIN -- Safe division IF v_divisor != 0 THEN v_result := 100 / v_divisor; ELSE v_result := NULL; -- Or raise custom error END IF;
-- Safe with NULLIF v_result := 100 / NULLIF(v_divisor, 0); -- Returns NULL if div by 0END;/Related Errors
Section titled “Related Errors”- ORA-00932 - Inconsistent datatypes
- ORA-01722 - Invalid number
- ORA-06512 - At line (PL/SQL stack trace)
- ORA-01476 - Divisor is equal to zero
- ORA-01403 - No data found
Summary Checklist
Section titled “Summary Checklist”- Always use %TYPE for variables that store column values
- Use generous sizes for computed or concatenated strings
- Validate input data before type conversion
- Handle NULL values explicitly
- Use exception handling for risky operations
- Test with boundary data including maximum length strings
- Use SUBSTR/ROUND/TRUNC when you must fit data into constrained variables