Skip to Main Content
  • Questions
  • Lenght of field becomes 32k or 4k depending on Oracle version

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Žilvinas.

Asked: May 14, 2020 - 3:36 pm UTC

Last updated: May 15, 2020 - 3:27 am UTC

Version: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Viewed 1000+ times

You Asked

Hello,

I recently studied one very strange bug.
And minimized code to to this:

BEGIN
  FOR i IN (SELECT *
              FROM (SELECT MAX(CAST('USD' AS CHAR(3))) OVER() c
                      FROM Dual))
  LOOP
    Dbms_Output.Put_Line(LENGTH(i.c));
  END LOOP;
END;


It outputs 32767 on Oracle 19 and 4000 on Oracle 12c.
Shouldn't the answer be 3?

Have a nice day

Žilvinas Vidmantas

and Connor said...

The difference between 4k and 32k is most probably unrelated to the version, but your database maximum string setting

SQL> show parameter max_string_size

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------
max_string_size                      string      EXTENDED


STANDARD = 4k, EXTENDED = 32k

That said, its still interesting that we don't come back with 3 in both cases. I think that's a bug.

Please log a bug with Support (it carries more weight coming from a customer than if I do it).

Here is some additional test cases you can add to it

SQL> declare
  2    x varchar2(100);
  3  BEGIN
  4    FOR i IN (SELECT MAX(CAST('USD' AS CHAR(3))) OVER() c FROM Dual)
  5    LOOP
  6      x := i.c;
  7    END LOOP;
  8  END;
  9  /

PL/SQL procedure successfully completed.

SQL>
SQL> declare
  2    x varchar2(100);
  3  BEGIN
  4    FOR i IN (SELECT *
  5                FROM (SELECT MAX(CAST('USD' AS CHAR(3))) OVER() c
  6                        FROM Dual))
  7    LOOP
  8      x := i.c;
  9    END LOOP;
 10  END;
 11  /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 8
ORA-06512: at line 8


SQL>
SQL> declare
  2    x clob;
  3  BEGIN
  4    FOR i IN (SELECT *
  5                FROM (SELECT MAX(CAST('USD' AS CHAR(3))) OVER() c
  6                        FROM Dual))
  7    LOOP
  8     select dump(i.c) into x from dual;
  9    END LOOP;
 10    dbms_output.put_line(x);
 11  END;
 12  /
Typ=96 Len=32767:
85,83,68,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,3
2,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,3
2,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
[snip]
,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,3
2,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,3
2,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,3
2,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32

PL/SQL procedure successfully completed.

SQL>
SQL>
SQL> declare
  2    x varchar2(100);
  3  BEGIN
  4    SELECT *
  5    into x
  6                FROM (SELECT MAX(CAST('USD' AS CHAR(3))) OVER() c
  7                        FROM Dual);
  8  END;
  9  /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4


SQL>
SQL>
SQL>



Is this answer out of date? If it is, please let us know via a Comment

More to Explore

Design

New to good database design? Check out Chris Saxon's full fundamentals class.