Skip to content

ORA-00917: Missing Comma - Fix Oracle SQL Syntax Errors

Error Text: ORA-00917: missing comma

The ORA-00917 error is a parse-time syntax error indicating that Oracle expected a comma separator at a specific position in the statement but encountered something else instead. It is most frequently encountered in SELECT column lists, INSERT VALUES clauses, column definition lists within CREATE TABLE or ALTER TABLE, and multi-row INSERT statements.

  • Forgetting the comma between two column names or expressions
  • Accidentally deleting a comma while editing a long SELECT list
  • Omitting a comma between adjacent literal values
  • Missing comma after a function call or expression in the values list

3. Missing Comma in CREATE TABLE Column Definitions

Section titled “3. Missing Comma in CREATE TABLE Column Definitions”
  • No comma between consecutive column definition lines
  • Removing a column from the middle of a CREATE TABLE without cleaning up surrounding commas
  • Omitting comma between row value groups in INSERT ALL or VALUES sets
  • Syntax errors in INSERT INTO ... VALUES (...), (...) (Oracle 23ai+)
  • Calling a function with multiple arguments but missing separator
  • Nested function calls where an inner argument list is incomplete

Identify Failed Parse Statements in Shared Pool

Section titled “Identify Failed Parse Statements in Shared Pool”
-- Find recently parsed-but-never-executed statements
SELECT
sql_id,
sql_text,
parse_calls,
executions,
last_active_time
FROM v$sql
WHERE parse_calls > 0
AND executions = 0
AND last_active_time > SYSDATE - 1/24
ORDER BY last_active_time DESC
FETCH FIRST 20 ROWS ONLY;
-- Unified audit trail for missing comma errors
SELECT
event_timestamp,
db_user_name,
os_user,
sql_text,
return_code
FROM unified_audit_trail
WHERE return_code = 917
AND event_timestamp > SYSTIMESTAMP - INTERVAL '1' DAY
ORDER BY event_timestamp DESC;

Check Alert Log for Repeated Application Errors

Section titled “Check Alert Log for Repeated Application Errors”
SELECT
originating_timestamp,
message_text
FROM v$diag_alert_ext
WHERE message_text LIKE '%ORA-00917%'
AND originating_timestamp > SYSTIMESTAMP - INTERVAL '24' HOUR
ORDER BY originating_timestamp DESC;
DECLARE
v_cursor INTEGER;
v_sql VARCHAR2(4000) :=
'SELECT employee_id last_name salary FROM employees'; -- missing commas
BEGIN
v_cursor := DBMS_SQL.OPEN_CURSOR;
BEGIN
DBMS_SQL.PARSE(v_cursor, v_sql, DBMS_SQL.NATIVE);
DBMS_OUTPUT.PUT_LINE('SQL is valid');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Parse error: ' || SQLERRM);
END;
DBMS_SQL.CLOSE_CURSOR(v_cursor);
END;
/
-- WRONG: Missing comma between column names
-- SELECT employee_id last_name salary department_id
-- FROM employees;
-- CORRECT
SELECT employee_id, last_name, salary, department_id
FROM employees;
-- WRONG: Missing comma after expression
-- SELECT employee_id
-- salary * 12 AS annual_sal
-- department_id
-- FROM employees;
-- CORRECT
SELECT
employee_id,
salary * 12 AS annual_sal,
department_id
FROM employees;
-- WRONG: Missing comma between values
-- INSERT INTO employees (employee_id, last_name, salary, department_id)
-- VALUES (200 'Smith' 50000 10);
-- CORRECT
INSERT INTO employees (employee_id, last_name, salary, department_id)
VALUES (200, 'Smith', 50000, 10);
-- WRONG: Missing comma after function call
-- INSERT INTO orders (order_id, order_date, total)
-- VALUES (1001 SYSDATE 500.00);
-- CORRECT
INSERT INTO orders (order_id, order_date, total)
VALUES (1001, SYSDATE, 500.00);
-- WRONG: Missing comma between column definitions
-- CREATE TABLE departments (
-- dept_id NUMBER
-- dept_name VARCHAR2(100)
-- location VARCHAR2(200)
-- );
-- CORRECT
CREATE TABLE departments (
dept_id NUMBER,
dept_name VARCHAR2(100),
location VARCHAR2(200)
);
-- WRONG: After removing a column, leftover missing comma
-- CREATE TABLE employees (
-- emp_id NUMBER,
-- -- removed middle_name column but forgot comma adjustment
-- last_name VARCHAR2(100)
-- salary NUMBER(10,2)
-- );
-- CORRECT
CREATE TABLE employees (
emp_id NUMBER,
last_name VARCHAR2(100),
salary NUMBER(10,2)
);

4. Fix Missing Comma in Function Arguments

Section titled “4. Fix Missing Comma in Function Arguments”
-- WRONG: Missing comma in TO_DATE arguments
-- SELECT TO_DATE('2024-01-01' 'YYYY-MM-DD') FROM dual;
-- CORRECT
SELECT TO_DATE('2024-01-01', 'YYYY-MM-DD') FROM dual;
-- WRONG: Missing comma in SUBSTR arguments
-- SELECT SUBSTR(last_name 1 5) FROM employees;
-- CORRECT
SELECT SUBSTR(last_name, 1, 5) FROM employees;
-- WRONG: Missing comma in DECODE
-- SELECT DECODE(status 'A' 'Active' 'I' 'Inactive' 'Unknown')
-- FROM users;
-- CORRECT
SELECT DECODE(status, 'A', 'Active', 'I', 'Inactive', 'Unknown')
FROM users;

5. Fix Multi-row INSERT Syntax (Oracle 23ai)

Section titled “5. Fix Multi-row INSERT Syntax (Oracle 23ai)”
-- WRONG: Missing comma between row groups
-- INSERT INTO departments (dept_id, dept_name)
-- VALUES (10, 'Sales')
-- (20, 'Finance')
-- (30, 'IT');
-- CORRECT (Oracle 23ai+)
INSERT INTO departments (dept_id, dept_name)
VALUES
(10, 'Sales'),
(20, 'Finance'),
(30, 'IT');
-- Alternative for older Oracle versions: INSERT ALL
INSERT ALL
INTO departments (dept_id, dept_name) VALUES (10, 'Sales')
INTO departments (dept_id, dept_name) VALUES (20, 'Finance')
INTO departments (dept_id, dept_name) VALUES (30, 'IT')
SELECT 1 FROM dual;
-- WRONG: Missing comma between SET assignments
-- UPDATE employees
-- SET salary = 60000
-- department_id = 20
-- WHERE employee_id = 100;
-- CORRECT
UPDATE employees
SET
salary = 60000,
department_id = 20
WHERE employee_id = 100;

7. Fix ALTER TABLE ADD Column Missing Comma

Section titled “7. Fix ALTER TABLE ADD Column Missing Comma”
-- WRONG: Adding multiple columns without comma separation
-- ALTER TABLE employees
-- ADD (middle_name VARCHAR2(50) phone VARCHAR2(20));
-- CORRECT
ALTER TABLE employees
ADD (
middle_name VARCHAR2(50),
phone VARCHAR2(20)
);

1. Use Trailing Comma Convention for Long Lists

Section titled “1. Use Trailing Comma Convention for Long Lists”
-- "Comma-first" style makes missing commas immediately visible
SELECT
employee_id
, last_name
, salary
, department_id
, hire_date
FROM employees
WHERE department_id = 50;

2. Consistent Indentation for INSERT Statements

Section titled “2. Consistent Indentation for INSERT Statements”
-- Align VALUES with column list for easy visual checking
INSERT INTO employees (
employee_id,
last_name,
first_name,
salary,
department_id,
hire_date
) VALUES (
201,
'Johnson',
'Maria',
55000,
30,
SYSDATE
);

3. Use DBMS_SQL for Dynamic SQL Validation

Section titled “3. Use DBMS_SQL for Dynamic SQL Validation”
-- Validate dynamically built SQL before execution
CREATE OR REPLACE FUNCTION is_valid_sql (p_sql IN VARCHAR2) RETURN BOOLEAN AS
v_cursor INTEGER;
BEGIN
v_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_cursor, p_sql, DBMS_SQL.NATIVE);
DBMS_SQL.CLOSE_CURSOR(v_cursor);
RETURN TRUE;
EXCEPTION
WHEN OTHERS THEN
IF DBMS_SQL.IS_OPEN(v_cursor) THEN
DBMS_SQL.CLOSE_CURSOR(v_cursor);
END IF;
RETURN FALSE;
END;
/
  • After every column name in a SELECT list: check for comma
  • After every value in an INSERT: check for comma
  • After every column definition in CREATE TABLE: check for comma
  • After removing any item from a list: verify surrounding commas
-- In SQL Developer: Ctrl+F7 formats the SQL and often reveals missing commas
-- The formatter will split items incorrectly, making the issue visible
SELECT employee_id last_name salary FROM employees;
-- After formatting, the lack of commas becomes immediately apparent
  1. Use EXPLAIN PLAN to locate the parse error without executing

    EXPLAIN PLAN FOR
    SELECT employee_id last_name FROM employees; -- Will fail with ORA-00917
  2. Break the statement into smaller pieces

    -- Test the SELECT list alone using dual
    SELECT employee_id, last_name, salary FROM dual; -- quick syntax check
  3. Count commas vs expected separators

    -- For a 5-column SELECT, you need exactly 4 commas
    -- For a 6-value INSERT, you need exactly 5 commas
    SELECT
    LENGTH('SELECT a, b, c FROM t')
    - LENGTH(REPLACE('SELECT a, b, c FROM t', ',', '')) AS comma_count
    FROM dual;
-- Confirm corrected statement parses cleanly
EXPLAIN PLAN FOR
SELECT employee_id, last_name, salary, department_id FROM employees;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-- If inside a stored procedure, recompile after fix
ALTER PROCEDURE my_procedure COMPILE;
-- Check for invalid objects after DDL fix
SELECT object_name, object_type, status
FROM user_objects
WHERE status = 'INVALID';