ORA-01400 Cannot Insert NULL into Column
ORA-01400: Cannot Insert NULL into Column
Section titled “ORA-01400: Cannot Insert NULL into Column”Error Overview
Section titled “Error Overview”Error Text: ORA-01400: cannot insert NULL into ("SCHEMA"."TABLE"."COLUMN")
The ORA-01400 error occurs when an INSERT or UPDATE statement attempts to place a NULL value into a column that has a NOT NULL constraint. The error message helpfully identifies the specific schema, table, and column involved.
Common Causes
Section titled “Common Causes”1. Missing Required Values
Section titled “1. Missing Required Values”- INSERT statement omitting required columns
- NULL passed from application code
- Empty strings converted to NULL
2. Data Loading Issues
Section titled “2. Data Loading Issues”- CSV/flat file with missing data
- ETL process not handling NULLs
- Source data quality problems
3. Trigger/Default Issues
Section titled “3. Trigger/Default Issues”- Trigger not setting required value
- Default value not defined
- Sequence not properly assigned
4. UPDATE to NULL
Section titled “4. UPDATE to NULL”- Setting column to NULL inadvertently
- Subquery returning NULL
- Conditional logic error
Diagnostic Queries
Section titled “Diagnostic Queries”Identify NOT NULL Columns
Section titled “Identify NOT NULL Columns”-- Find all NOT NULL columns for a tableSELECT column_name, data_type, nullable, data_defaultFROM user_tab_columnsWHERE table_name = UPPER('&table_name') AND nullable = 'N'ORDER BY column_id;
-- Check specific columnSELECT column_name, nullable, data_defaultFROM user_tab_columnsWHERE table_name = UPPER('&table_name') AND column_name = UPPER('&column_name');
-- Find NOT NULL columns without defaultsSELECT column_name, data_typeFROM user_tab_columnsWHERE table_name = UPPER('&table_name') AND nullable = 'N' AND data_default IS NULLORDER BY column_id;Check Constraint Details
Section titled “Check Constraint Details”-- Find NOT NULL constraintsSELECT constraint_name, search_conditionFROM user_constraintsWHERE table_name = UPPER('&table_name') AND constraint_type = 'C' -- Check constraints AND search_condition LIKE '%NOT NULL%';
-- All constraints on columnSELECT constraint_name, constraint_typeFROM user_cons_columns ccJOIN user_constraints c USING (constraint_name)WHERE cc.table_name = UPPER('&table_name') AND cc.column_name = UPPER('&column_name');Find NULL Source in Data
Section titled “Find NULL Source in Data”-- Check source data for NULLsSELECT COUNT(*) as null_countFROM source_tableWHERE target_column IS NULL;
-- Find rows with NULL that would failSELECT *FROM source_tableWHERE target_column IS NULL;
-- Identify NULL patterns in stagingSELECT column_name, COUNT(CASE WHEN value IS NULL THEN 1 END) as null_count, COUNT(*) as total_rowsFROM staging_tableUNPIVOT (value FOR column_name IN (col1, col2, col3))GROUP BY column_name;Resolution Steps
Section titled “Resolution Steps”1. Provide Required Values
Section titled “1. Provide Required Values”-- Wrong: Missing required columnINSERT INTO employees (first_name, last_name)VALUES ('John', 'Doe');-- Fails if employee_id is NOT NULL
-- Right: Include all required columnsINSERT INTO employees (employee_id, first_name, last_name)VALUES (emp_seq.NEXTVAL, 'John', 'Doe');2. Add Default Value to Column
Section titled “2. Add Default Value to Column”-- Add default for existing columnALTER TABLE employees
-- Add default with NOT NULLALTER TABLE employeesMODIFY status VARCHAR2(20) DEFAULT 'ACTIVE' NOT NULL;
-- Check the changeSELECT column_name, data_defaultFROM user_tab_columnsWHERE table_name = 'EMPLOYEES' AND column_name = 'EMAIL';3. Use NVL/COALESCE for NULL Handling
Section titled “3. Use NVL/COALESCE for NULL Handling”-- In INSERT statementINSERT INTO employees (employee_id, first_name, last_name, email)VALUES ( emp_seq.NEXTVAL, 'John', 'Doe',);
-- In INSERT...SELECTINSERT INTO employees (employee_id, first_name, last_name, email)SELECT emp_seq.NEXTVAL, first_name, last_name,FROM staging_employees;
-- With CASE expressionINSERT INTO employees (employee_id, first_name, last_name, status)SELECT emp_seq.NEXTVAL, first_name, last_name, CASE WHEN status IS NULL THEN 'PENDING' ELSE status ENDFROM staging_employees;4. Create Trigger for Auto-Population
Section titled “4. Create Trigger for Auto-Population”-- Trigger to set default valuesCREATE OR REPLACE TRIGGER trg_emp_defaultsBEFORE INSERT ON employeesFOR EACH ROWBEGIN -- Auto-generate ID if null IF :NEW.employee_id IS NULL THEN :NEW.employee_id := emp_seq.NEXTVAL; END IF;
-- Set default email if null IF :NEW.email IS NULL THEN :NEW.email := LOWER(:NEW.first_name || '.' || :NEW.last_name || '@company.com'); END IF;
-- Set creation timestamp IF :NEW.created_date IS NULL THEN :NEW.created_date := SYSDATE; END IF;END;/5. Make Column Nullable (If Appropriate)
Section titled “5. Make Column Nullable (If Appropriate)”-- Only if business rules allow NULLALTER TABLE employees MODIFY middle_name NULL;
-- Verify changeSELECT column_name, nullableFROM user_tab_columnsWHERE table_name = 'EMPLOYEES' AND column_name = 'MIDDLE_NAME';6. Fix UPDATE Statements
Section titled “6. Fix UPDATE Statements”-- Wrong: Updating to NULLUPDATE employees SET email = NULL WHERE employee_id = 100;
-- Right: Use NVL to prevent NULLUPDATE employeesSET email = NVL(v_new_email, email) -- Keep existing if new is NULLWHERE employee_id = 100;
-- Right: Use NULLIF carefullyUPDATE employeesSET department_id = NULLIF(v_dept_id, 0) -- Could return NULL!WHERE employee_id = 100;-- Better:UPDATE employeesSET department_id = CASE WHEN v_dept_id = 0 THEN department_id ELSE v_dept_id ENDWHERE employee_id = 100;Prevention Strategies
Section titled “Prevention Strategies”1. Input Validation in Application
Section titled “1. Input Validation in Application”-- PL/SQL validation before insertCREATE OR REPLACE PROCEDURE insert_employee( p_first_name VARCHAR2, p_last_name VARCHAR2, p_email VARCHAR2) ASBEGIN -- Validate required fields IF p_first_name IS NULL THEN RAISE_APPLICATION_ERROR(-20001, 'First name is required'); END IF;
IF p_last_name IS NULL THEN RAISE_APPLICATION_ERROR(-20002, 'Last name is required'); END IF;
INSERT INTO employees (employee_id, first_name, last_name, email)
COMMIT;END;/2. Data Loading with NULL Handling
Section titled “2. Data Loading with NULL Handling”-- SQL*Loader control file with NULL handling-- LOAD DATA-- INFILE 'employees.csv'-- INTO TABLE employees-- FIELDS TERMINATED BY ','-- (-- employee_id SEQUENCE(MAX,1),-- first_name,-- last_name,-- email "NVL(:email, '[email protected]')"-- )
-- PL/SQL bulk load with NULL handlingDECLARE TYPE t_emp_tab IS TABLE OF employees%ROWTYPE; v_employees t_emp_tab;BEGIN -- Load from staging SELECT staging_seq.NEXTVAL, first_name, last_name, NVL(hire_date, SYSDATE) BULK COLLECT INTO v_employees FROM staging_employees;
FORALL i IN 1..v_employees.COUNT INSERT INTO employees VALUES v_employees(i);
COMMIT;END;/3. Define Sensible Defaults at Table Creation
Section titled “3. Define Sensible Defaults at Table Creation”CREATE TABLE employees ( employee_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, first_name VARCHAR2(50) NOT NULL, last_name VARCHAR2(50) NOT NULL, status VARCHAR2(20) DEFAULT 'ACTIVE' NOT NULL, created_date DATE DEFAULT SYSDATE NOT NULL, created_by VARCHAR2(30) DEFAULT USER NOT NULL);4. Use Check Constraints for Additional Validation
Section titled “4. Use Check Constraints for Additional Validation”-- Prevent empty strings that might be confused with NULLALTER TABLE employees ADD CONSTRAINT chk_fname_not_emptyCHECK (first_name IS NOT NULL AND LENGTH(TRIM(first_name)) > 0);
ALTER TABLE employees ADD CONSTRAINT chk_lname_not_emptyCHECK (last_name IS NOT NULL AND LENGTH(TRIM(last_name)) > 0);Common Scenarios
Section titled “Common Scenarios”Empty String vs NULL
Section titled “Empty String vs NULL”-- In Oracle, empty string '' equals NULL!INSERT INTO employees (employee_id, first_name, last_name)VALUES (100, 'John', ''); -- This becomes NULL and fails if last_name is NOT NULL
-- Solution: Check for empty stringsINSERT INTO employees (employee_id, first_name, last_name)VALUES (100, 'John', NVL(NULLIF(TRIM(v_last_name), ''), 'Unknown'));Conditional Insert
Section titled “Conditional Insert”-- Ensure value exists in all branchesINSERT INTO employees (employee_id, first_name, last_name, department_id)VALUES ( 100, 'John', 'Doe', CASE WHEN v_is_manager THEN 10 WHEN v_is_contractor THEN 20 ELSE 30 -- Don't forget the ELSE! END);Related Errors
Section titled “Related Errors”- ORA-01407 - Cannot update to NULL
- ORA-02290 - Check constraint violated
- ORA-00947 - Not enough values
- ORA-01722 - Invalid number
Emergency Response
Section titled “Emergency Response”Quick Identification
Section titled “Quick Identification”-- Parse error message for column info-- Error: ORA-01400: cannot insert NULL into ("HR"."EMPLOYEES"."EMAIL")-- Schema: HR, Table: EMPLOYEES, Column: EMAIL
-- Check column requirementsSELECT nullable, data_defaultFROM dba_tab_columnsWHERE owner = 'HR' AND table_name = 'EMPLOYEES' AND column_name = 'EMAIL';Temporary Fix
Section titled “Temporary Fix”-- Add temporary default (fix properly later)
-- Or create trigger for complex defaultsCREATE OR REPLACE TRIGGER trg_emp_emailBEFORE INSERT ON employeesFOR EACH ROWWHEN (NEW.email IS NULL)BEGIN :NEW.email := 'auto_' || :NEW.employee_id || '@company.com';END;/