VARCHAR2
, NVARCHAR2
, and RAW
data types (Extended Data Types) provided that MAX_STRING_SIZE = EXTENDED
.
What I recently discovered is that SYS can create such columns even when MAX_STRING_SIZE = STANDARD
. It is possible in 12.2, 18c, 19c. I am unsure about 12.1 since I do not have any of those.
Firstly, let us try to create a table with a
VARCHAR2(32767)
column as non-SYS user:
SQL> conn tc/tc@localhost/pdb2 Connected. SQL> sho parameter max_string_size NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ max_string_size string STANDARD SQL> select banner_full from v$version; BANNER_FULL -------------------------------------------------------------------------------- Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.10.0.0.0 SQL> create table t(c varchar2(32767)); create table t(c varchar2(32767)) * ERROR at line 1: ORA-00910: specified length too long for its datatypeIt fails as expected.
Now I try the same as SYS - I also switch to my root container to verify that
MAX_STRING_SIZE = STANDARD
everywhere:
SQL> conn sys/Oracle123@localhost/orcl2 as sysdba Connected. SQL> alter session set container=cdb$root; Session altered. SQL> sho parameter max_string_size NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ max_string_size string STANDARD SQL> alter session set container=pdb2; Session altered. SQL> sho parameter max_string_size NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ max_string_size string STANDARD SQL> select banner_full from v$version; BANNER_FULL -------------------------------------------------------------------------------- Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.10.0.0.0 SQL> create table t(c varchar2(32767)); Table created. SQL> desc t Name Null? Type ----------------------------------------- -------- ---------------------------- C VARCHAR2(32767)Let us try to run a DML command:
SQL> insert into t values (lpad('x',32767,'x')); 1 row created. SQL> select length(c) from t; LENGTH(C) ---------- 4000Although it was possible to create a 32K column, somewhere between
LPAD
and the data layer I still got 4,000 bytes only.But is it limited to 4,000 bytes? Not really as the example below demonstrates:
SQL> update t 2 set c=c||'y'; 1 row updated. SQL> select length(c) from t; LENGTH(C) ---------- 4001 SQL> SQL> update t 2 set c=c||c; 1 row updated. SQL> select length(c) from t; LENGTH(C) ---------- 8002 SQL> SQL> update t 2 set c=c||c; 1 row updated. SQL> select length(c) from t; LENGTH(C) ---------- 16004 SQL> SQL> update t 2 set c=c||c; 1 row updated. SQL> select length(c) from t; LENGTH(C) ---------- 32008 SQL> SQL> update t 2 set c=c||c; update t * ERROR at line 1: ORA-01489: result of string concatenation is too long SQL> select length(c) from t; LENGTH(C) ---------- 32008 SQL> SQL> update t 2 set c=c||lpad('x',759,'x'); 1 row updated. SQL> select length(c) from t; LENGTH(C) ---------- 32767 SQL> SQL> update t 2 set c=c||'x'; update t * ERROR at line 1: ORA-01489: result of string concatenation is too long SQL> select length(c) from t; LENGTH(C) ---------- 32767As expected Oracle stores the column as LOB under the hood:
SQL> select dbms_metadata.get_ddl('TABLE', 'T') from dual; DBMS_METADATA.GET_DDL('TABLE','T') -------------------------------------------------------------------------------- CREATE TABLE "SYS"."T" ( "C" VARCHAR2(32767) ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "SYSTEM" SQL> SQL> select column_name, segment_name, index_name, securefile 2 from user_lobs 3 where table_name='T'; COLUMN_NAME SEGMENT_NAME INDEX_NAME SECUREFILE ----------- ------------------------- ------------------------- ---------- C SYS_LOB0000023954C00001$$ SYS_IL0000023954C00001$$ NOTurns out that Oracle uses that internally:
SQL> drop table t; Table dropped. SQL> SQL> select table_name, column_name, data_length 2 from user_tab_cols 3 where data_type = 'VARCHAR2' 4 and data_length > 4000; TABLE_NAME COLUMN_NAME DATA_LENGTH ------------------------- -------------------- ----------- OPATCH_SQL_PATCHES NODE_NAMES 32000 SYSDBIMFS_METADATA$ VALUE 4096 SCHEDULER$_CREDENTIAL KEY 32767 V_$DIAG_LOG_EXT SUPPLEMENTAL_DETAILS 4003Originally I discovered that Oracle uses
VARCHAR2(32767)
in its scripts which threw me into a tizzy since the scripts were running without errors in MAX_STRING_SIZE = STANDARD
databases.It is yet another confirmation that it is not a good idea to use
SYS
to do things. SYS
is a "special" user.
Комментариев нет:
Отправить комментарий
Примечание. Отправлять комментарии могут только участники этого блога.