'Getting error "ORA-54033" when calling a procedure

I'm currently getting the following Oracle error when calling a procedure:

ORA-54033: column to be modified is used in a virtual column expression

How can I track down the root cause of this error?



Solution 1:[1]

To find the table and column names of all virtual columns in your database you can run the following query:

SELECT c.OWNER, c.TABLE_NAME, c.COLUMN_NAME
  FROM DBA_TAB_COLS c
  WHERE c.VIRTUAL_COLUMN = 'YES' AND
        c.OWNER NOT IN ('SYS', 'XDB')
  ORDER BY c.OWNER, c.TABLE_NAME, c.COLUMN_NAME;

And you can use the following script to dump the DDL of all tables in your database which contain virtual columns to DBMS_OUTPUT:

DECLARE
  lobDDL  CLOB;

  PROCEDURE dump_clob(aCLOB IN CLOB) IS
    nCLOB_length       NUMBER;
    nCLOB_offset       NUMBER := 1;
    nMax_chunk_size    NUMBER := 32767;
    strChunk           VARCHAR2(32767);
  BEGIN
    nCLOB_length := DBMS_LOB.GETLENGTH(aCLOB);

    WHILE nCLOB_offset <= nCLOB_length LOOP
      strChunk := DBMS_LOB.SUBSTR(aCLOB, nMax_chunk_size, nCLOB_offset);

      DBMS_OUTPUT.PUT(strChunk);

      nCLOB_offset := nCLOB_offset + LENGTH(strChunk);
    END LOOP;

    DBMS_OUTPUT.PUT_LINE(';');
  END dump_clob;
BEGIN
  FOR aRow IN (SELECT DISTINCT c.OWNER, c.TABLE_NAME
                 FROM DBA_TAB_COLS c
                 WHERE c.VIRTUAL_COLUMN = 'YES' AND
                       c.OWNER NOT IN ('SYS', 'XDB')
                 ORDER BY c.OWNER, c.TABLE_NAME)
  LOOP
    lobDDL := DBMS_METADATA.GET_DDL(object_type => 'TABLE',
                                    name        => aRow.TABLE_NAME,
                                    schema      => aRow.OWNER);

    dump_clob(lobDDL);
  END LOOP;
END;

Solution 2:[2]

I got the same error and fixed it by doing as below.

Get the hidden columns with its dependent columns using the below.

SELECT COLUMN_NAME, DATA_DEFAULT, HIDDEN_COLUMN
FROM   USER_TAB_COLS
WHERE  TABLE_NAME = 'YOUR_TABLE_NAME';

You should see something like this below:

SYS_STUMF_$2WEF286CDZ1WPC4V_F5    |SYS_OP_COMBINED_HASH("ID","FIRST_NAME","ANOTHER_COLUMN_NAME") | YES

Drop this hidden column by using the above column names used by it.

exec dbms_stats.drop_extended_stats(user, 'YOUR_TABLE_NAME', '("ID","FIRST_NAME","ANOTHER_COLUMN_NAME") ');

Now run your procedure or alter your columns.

alter table YOUR_TABLE_NAME modify (ID VARCHAR2(10));

Create the hidden column again:

exec dbms_stats.create_extended_stats(user, 'YOUR_TABLE_NAME', '("ID","FIRST_NAME","ANOTHER_COLUMN_NAME")');

Solution 3:[3]

I am just sharing my experience here with this issue.

My table has the below virtual column. There are other columns as well, and I am just adding the impacted columns here.

Create Table Virtual_test
(ColumnA varchar2(100),
CLEAN_ColumnA VARCHAR2(4000 BYTE) GENERATED ALWAYS
AS(GET_CLEAN_ColumnA(ColumnA)) VIRTUAL
);

Now when I want to modify the size of ColumnA:

Alter Table Virtual_test
MODIFY ColumnA varchar2(255);

ORA-54033: column to be modified is used in a virtual column expression.

exec dbms_stats.drop_extended_stats(USER,'Virtual_test','(GET_CLEAN_ColumnA(ColumnA))' );

Alter Table Virtual_test
MODIFY ColumnA varchar2(255);

One major mistake I did was this virtual column was not hidden and not system generated in my table.

The step dbms_stats.drop_extended_stats deleted my existing column and dbms_stats.create_extended_stats will create an invisible column with the system generated name.

So I think this won't work with a non-hidden column, and you may need to follow the below steps and drop the column.

Alter Table Virtual_test drop column CLEAN_ColumnA;

Alter Table Virtual_test
MODIFY ColumnA varchar2(255);


Alter Table Virtual_test add
CLEAN_ColumnA VARCHAR2(4000 BYTE) GENERATED ALWAYS
AS(GET_CLEAN_ColumnA(ColumnA)) VIRTUAL;

Solution 4:[4]

The virtual column names starting with 'SYS_ST%' are indeed belonging to extended statistics... and since Oracle 12c, the system is trying to recognize and create them automatically...

Just google for "Oracle 12c Automatic Column Group Detection".

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter Mortensen
Solution 2 Peter Mortensen
Solution 3 Peter Mortensen
Solution 4 Peter Mortensen