After you can slice and glue strings, you need to find them and measure them. DB2 for z/OS provides LOCATE and POSITION to search, LENGTH and OCTET_LENGTH to measure, and LEFT / RIGHT (also spelled STRLEFT / STRRIGHT) to take an end of a string. Positions are 1-based. Zero usually means “not found.” Bytes are not always characters. This page walks through each function with the rules from the SQL Reference.
LOCATE returns the position at which the first occurrence of a search string starts within a source string. Schema is SYSIBM.
1LOCATE(search-string, source-string [, start [, CODEUNITS16 | CODEUNITS32 | OCTETS]])
Result rules:
123456SELECT LOCATE('HAAS', LASTNAME) AS POS FROM DSN8C10.EMP WHERE EMPNO = '000010'; -- 1 if LASTNAME is HAAS SELECT LOCATE('E', 'CHRISTINE', 4) AS NEXT_E FROM SYSIBM.SYSDUMMY1; -- next E at or after position 4
COBOL programmers sometimes expect 0-based indexes or −1 for “not found.” In DB2, 0 means not found and 1 means the first character. Test with > 0 when you mean “contains.”
123SELECT EMPNO, LASTNAME FROM DSN8C10.EMP WHERE LOCATE('SON', LASTNAME) > 0;
POSITION is the SQL-standard spelling of the same search. Typical form:
1POSITION(search-string IN source-string [USING CODEUNITS16 | CODEUNITS32 | OCTETS])
IBM documents that LOCATE without start is similar to POSITION with the same string units, and LOCATE with start is similar to POSITION on SUBSTRING(source FROM start). Use POSITION when you want standard SQL. Use LOCATE when you need the optional start argument in one function call — that is the everyday z/OS pattern.
Related names you will see in manuals: POSSTR and STRPOS (search in a slightly different argument order / synonym family), and INSTR / LOCATE_IN_STRING for Oracle-style or extra occurrence arguments. Stick to LOCATE and POSITION in new Db2 for z/OS code unless a portability guide at your shop says otherwise.
LENGTH returns the length of a value. The argument can be any built-in type except XML. The result is a large integer and can be null.
1LENGTH(expression)
For strings:
12345678SELECT LENGTH(FIRSTNME) FROM DSN8C10.EMP WHERE EMPNO = '000280'; -- 5 when FIRSTNME is ETHEL SELECT LENGTH(HIREDATE) AS RAW_DATE, -- 4 LENGTH(CHAR(HIREDATE, EUR)) AS CHAR10 -- 10 FROM DSN8C10.EMP WHERE EMPNO = '000010';
| Type | LENGTH result |
|---|---|
| Character / binary / graphic string | Actual string length in bytes (graphic: as documented for the type); blanks included |
| SMALLINT | 2 |
| INTEGER | 4 |
| BIGINT | 8 |
| DECIMAL(p) | Integer part of (p/2)+1 |
| DATE | 4 |
| TIME | 3 |
| TIMESTAMP | 10 (without precision extras; TIMESTAMP(p) is 7+((p+1)/2)) |
| DECFLOAT(16) / (34) | 8 / 16 |
Beginners often write LENGTH(DATECOL) expecting 10. Internal DATE is 4 bytes. Format it with CHAR or VARCHAR first if you want the display length.
OCTET_LENGTH returns the length of a string in octets (bytes). Schema SYSIBM. Use it when you mean “how much storage / how many bytes” and you want the standard function name. For Unicode data, byte length and character length diverge; OCTET_LENGTH stays on the byte side. CHARACTER_LENGTH with CODEUNITS32 answers “how many characters.”
1234SELECT LENGTH(FIRSTNME) AS LEN_BYTES, OCTET_LENGTH(FIRSTNME) AS OCTETS FROM DSN8C10.EMP WHERE EMPNO = '000010';
On simple EBCDIC SBCS names, LENGTH and OCTET_LENGTH match. On UTF-8, a name with ü has more octets than CODEUNITS32 characters. Buffer sizes in COBOL PIC X(n) and VARCHAR host variables care about octets.
LEFT returns the leftmost units of a string. RIGHT returns the rightmost units. STRLEFT is a synonym for LEFT; STRRIGHT is a synonym for RIGHT (function-level compatibility).
12LEFT(string-expression, integer [, CODEUNITS16 | CODEUNITS32 | OCTETS]) RIGHT(string-expression, integer [, CODEUNITS16 | CODEUNITS32 | OCTETS])
The result is a varying-length string with the same length attribute as the source. IBM’s Jürgen example:
1234567-- FIRSTNME / literal 'Jürgen' in UTF-8 LEFT(FIRSTNME, 2, CODEUNITS32) -- 'Jü' LEFT(FIRSTNME, 2, CODEUNITS16) -- 'Jü' LEFT(FIRSTNME, 2, OCTETS) -- truncated ('J' plus blank) RIGHT(FIRSTNME, 5, CODEUNITS32) -- 'ürgen' RIGHT(FIRSTNME, 5, OCTETS) -- truncated byte slice
LEFT(s, n) is the Unicode-aware cousin of SUBSTR(s, 1, n). RIGHT(s, n) is harder to fake with SUBSTR because you need LENGTH (in the same units) first. Prefer RIGHT instead of computing start = LENGTH − n + 1, especially on UTF-8.
123SELECT LEFT(EMPNO, 3) AS PREFIX, -- department-style prefix if EMPNO layout agrees RIGHT(EMPNO, 3) AS SUFFIX FROM DSN8C10.EMP;
Several functions on this page share the same unit keywords:
Mixing units in one expression (LENGTH in bytes, LEFT in CODEUNITS32) is a common bug. Pick one unit system for a given column’s encoding and stay with it.
A typical parse: find a separator, then take the left or right piece.
12345SELECT LASTNAME, LOCATE(',', LASTNAME) AS COMMA_AT, LEFT(LASTNAME, LOCATE(',', LASTNAME) - 1) AS BEFORE_COMMA FROM SOME_TABLE WHERE LOCATE(',', LASTNAME) > 0;
Guard the LOCATE > 0 test. LEFT(..., −1) from a missing comma is not a valid length. In COBOL you would do the same with two statements and a host variable for the position.
LENGTH is a ruler: it tells you how long the sticker is. On some stickers the ruler counts centimetres of paper (bytes). A fancy letter can be wider than one centimetre, so the ruler and a person counting letters can disagree — that is OCTETS versus CODEUNITS32. LOCATE is peeking along the sticker for a tiny word and shouting the tile number where it starts, starting at one, or shouting zero if it is not there. LEFT keeps the beginning of the sticker; RIGHT keeps the end.
1. What does LOCATE return when the search string is not found (and neither argument is null)?
2. What does LOCATE return if the search string has length zero?
3. LENGTH of VARCHAR value ETHEL (5 characters stored) returns:
4. LENGTH of a DATE column returns:
5. LEFT(name, 2, OCTETS) on UTF-8 Jürgen can differ from LEFT(name, 2, CODEUNITS32) because: