ORA-01008: Not All Variables Bound — Causes, Fixes, and Prevention
ORA-01008 is thrown by Oracle when the number of bind variables declared in a SQL statement does not match the number of variables actually bound before execution. Simply put, you've used placeholders like :1, :2, or :name in your SQL, but failed to supply a value for each one. This error commonly appears in PL/SQL dynamic SQL, JDBC applications, Python (cx_Oracle/oracledb), and OCI programs.
Top 3 Causes
1. Mismatched Number of Bind Variables
The most common cause: your SQL has three placeholders but your code only binds two values.
-- WRONG: Three bind variables in SQL, only two bound in USING clause
DECLARE
v_id NUMBER := 101;
v_name VARCHAR2(50) := 'Alice';
BEGIN
-- :3 (dept_id) is never bound → ORA-01008
EXECUTE IMMEDIATE
'INSERT INTO employees (emp_id, emp_name, dept_id) VALUES (:1, :2, :3)'
USING v_id, v_name; -- Missing third bind value!
END;
/
-- CORRECT: All three placeholders are bound
DECLARE
v_id NUMBER := 101;
v_name VARCHAR2(50) := 'Alice';
v_dept NUMBER := 10;
BEGIN
EXECUTE IMMEDIATE
'INSERT INTO employees (emp_id, emp_name, dept_id) VALUES (:1, :2, :3)'
USING v_id, v_name, v_dept; -- All three bound correctly
COMMIT;
END;
/
2. Repeated Bind Variable Names Across Different APIs
In Oracle PL/SQL, a named bind variable used multiple times in a statement only needs to be bound once. However, in JDBC (positional binding) or some other drivers, each occurrence must be bound separately. Misunderstanding this behavior is a frequent source of ORA-01008.
-- PL/SQL: Same named variable used twice — bind ONCE (Oracle handles duplication)
DECLARE
v_dept NUMBER := 20;
v_count NUMBER;
BEGIN
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM employees
WHERE dept_id = :dept OR manager_dept = :dept'
INTO v_count
USING v_dept; -- Only one USING entry needed in PL/SQL
DBMS_OUTPUT.PUT_LINE('Count: ' || v_count);
END;
/
-- JDBC positional binding (Java pseudo-SQL comment):
-- String sql = "SELECT COUNT(*) FROM employees WHERE dept_id = ? OR manager_dept = ?";
-- pstmt.setInt(1, 20); // First occurrence
-- pstmt.setInt(2, 20); // Second occurrence — must be bound separately!
SELECT 'Always bind each positional ? separately in JDBC' AS reminder FROM dual;
3. Dynamic SQL Construction Errors
When SQL is built conditionally at runtime, it's easy to add a bind variable to the SQL string but forget to include the corresponding value in the binding call — or vice versa.
-- Dangerous pattern: SQL and bind values built independently
DECLARE
v_sql VARCHAR2(1000);
v_dept NUMBER := 10;
v_salary NUMBER := NULL; -- Not used this time
v_count NUMBER;
BEGIN
v_sql := 'SELECT COUNT(*) FROM employees WHERE dept_id = :1';
-- BUG: v_salary condition added to SQL but binding not updated
-- v_sql := v_sql || ' AND salary > :2'; -- If uncommented without adding USING value → ORA-01008
EXECUTE IMMEDIATE v_sql INTO v_count USING v_dept;
DBMS_OUTPUT.PUT_LINE('Result: ' || v_count);
END;
/
-- Safe pattern: Always synchronize SQL construction with bind value list
DECLARE
v_sql VARCHAR2(1000) := 'SELECT COUNT(*) FROM employees WHERE 1=1';
v_dept NUMBER := 10;
v_salary NUMBER := 5000;
v_count NUMBER;
BEGIN
-- Build SQL and bind values together
v_sql := v_sql || ' AND dept_id = :1 AND salary >= :2';
EXECUTE IMMEDIATE v_sql INTO v_count USING v_dept, v_salary;
DBMS_OUTPUT.PUT_LINE('Result: ' || v_count);
END;
/
Quick Fix Solutions
-
Count your placeholders: Count every
:1,:2,:nametoken in your SQL string and ensure yourUSINGclause or binding calls match exactly. - Log the SQL before execution: Print or log the full SQL string in development so you can visually inspect variable counts when errors occur.
-
Use
V$SQL_BIND_CAPTURE: Query this view to inspect bind variable metadata for recently executed statements on the database side.
-- Check bind variable info for a specific SQL statement
SELECT sql_id, name, position, datatype_string, value_string
FROM v$sql_bind_capture
WHERE sql_id = 'your_sql_id_here'
ORDER BY position;
Prevention Tips
- Code review checklist: Always review the SQL string and its binding code together. Make it a team rule that the number of bind tokens must visually match the number of bound values in every pull request.
- Unit test all parameter combinations: Test dynamic SQL procedures with every meaningful combination of inputs, including NULLs and edge cases, to catch binding mismatches before they reach production.
Related Errors
- ORA-01006 — Bind variable does not exist: You referenced a variable name in the bind call that doesn't appear in the SQL.
- ORA-01036 — Illegal variable name/number: The bind variable name violates Oracle naming rules.
- ORA-00904 — Invalid identifier: Often confused with bind variable errors when column names or aliases are mistyped.
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)