SQLCODE -312: Host variable not defined or not usable
SQLCODE -312 (SQLSTATE 42618) means an SQL statement refers to a host variable that Db2 can't use. Either no declaration for that name was found, its data type doesn't fit the way the statement uses it, or it sits inside a dynamic statement where host variables aren't allowed.
Other names for this code
Also written as SQL -312, SQLCODE=-312, SQLCODE = -312, db2 -312, sqlstate 42618, SQL0312N, DSNH312I, undefined or unusable host variable, SQL0312, variable is not defined or not usable.
What it means
For static SQL, you meet -312 when the program is prepared, not when it runs. The Db2 precompiler, or the Db2 coprocessor inside the compiler, reads the program's data declarations and then matches every :name in each EXEC SQL statement against them. If it can't find the name, or the variable's type makes no sense where it's used, it flags -312 with the variable name. The program can't be bound until it's fixed.
Dynamic SQL is different. A statement string you PREPARE or EXECUTE IMMEDIATE can't contain host variable references at all. Db2 has no way to see the program's storage when it compiles the string at run time, so the string has to use ? parameter markers. The values then go in on EXECUTE or OPEN with a USING clause.
Older Db2 for z/OS releases titled the message "undefined or unusable host variable". Db2 12 says the variable is not defined or not usable. The meaning is unchanged, and it now also covers SQL variables in native SQL procedures, functions and triggers.
Common causes
- The name is misspelled in the EXEC SQL statement, or differs from the declaration by a hyphen or a suffix.
- The variable is declared in a member brought in with a COBOL COPY statement. The separate Db2 precompiler expands EXEC SQL INCLUDE but not COPY, so it never sees those fields. The coprocessor does process COPY.
- The variable's type doesn't fit its use, for example a numeric field given as the statement text on a PREPARE, or a group item where Db2 needs a single field.
- A dynamic statement string contains
:name. This happens when SQL is copied from a static program into a string that gets prepared. - In a native SQL procedure, SQL function or trigger body, a name is used that isn't declared as an SQL variable or parameter in scope at that point.
- The declaration was removed or renamed during a change, but an EXEC SQL statement still uses the old name.
- A host variable is used in an index key expression, where variables aren't allowed.
How to find the problem
- Read the precompiler or coprocessor listing. The message gives the statement line and the variable name.
- Search the program source, including copybooks, for the exact name. Check whether the declaration sits in a COPY member rather than an EXEC SQL INCLUDE member.
- Check the declaration's PIC and USAGE against the way the statement uses the variable.
- For dynamic SQL, display the final statement string before the PREPARE and look for a colon followed by a name.
How to fix it
- Correct the spelling or add the missing declaration.
- Change
COPY CUSTRECtoEXEC SQL INCLUDE CUSTREC END-EXEC, or switch the build to the Db2 coprocessor (the SQL compiler option), which handles COPY. - Change the declaration to a type that fits the use. Let DCLGEN generate declarations for table columns.
- In dynamic SQL, replace each host variable in the string with
?and pass the values withEXECUTE stmt USING :WS-ACCT, :WS-DATEorOPEN cursor USING .... - Precompile again and rebind once the listing is clean.
IBM documentation
IBM documentation: -312. Use the documentation for your installed release.
Related codes
Questions
Why does -312 show up at precompile and not at run time?
For static SQL the precompiler checks every host variable before the program is bound. A program with a -312 never gets a valid package, so it can't run with that statement.
Can I put :host-variable inside a statement I PREPARE?
No. Use a ? parameter marker in the string and supply the value with USING on EXECUTE or OPEN.
Does SQL0312N on Db2 for LUW mean the same thing?
Mostly. On LUW, SQL0312N with SQLSTATE 42618 is about a host variable used in a dynamic statement, a view definition or a trigger definition. IBM i uses SQL0312 for a variable that isn't defined or isn't usable, like z/OS.