Why does this Oracle DROP COLUMN alter the default value of another column?
This is an Oracle bug.
It is triggered by adding a column with both a NOT NULL
constraint and a DEFAULT
value to an existing table.
To add the column quickly, Oracle 11g stores the default value in the data dictionary. Oracle calls this "add column optimization".
This is faster than writing out the default value into every table row. The query engine is then supposed to replace any NULL in the table row with the default value from the data dictionary. Unfortunately there are several bugs related to this. Yours appears to be an instance of:
17325413 Drop column with DEFAULT value and NOT NULL definition ends
up with dropped column data hitting disk leading to corruption
You can check which columns have been added like this:
select owner, object_name, name
from dba_objects, col$
where bitand(col$.PROPERTY,1073741824)=1073741824
and object_id=obj#;
In our case, we were stung by a different bug which returned the incorrect results for a SELECT FOR UPDATE
.
We set parameter _add_col_optim_enabled=FALSE
to turn off this "optimisation". Alternatively, you may be able to upgrade to a later Oracle version where these bugs are resolved.
Upgrading or setting the above parameter will not fix your existing table, which is corrupt. You must re-create that table.
Modify a column to remove or change default value in oracle 11g
Column C2 current definition:
C2 date default sysdate
When you're altering this column to VARCHAR2(10) there is no problem, because Oracle performs an implicit conversion of the values from DATE to VARCHAR2 using current NLS_SETTINGS (date string representation pattern for example)
When you're altering the column to NUMBER(9) Oracle cannot apply an implicit conversion (there is no such rule in its conversion matrix). That's why you're getting an error.
One way to alter is to make the column null:
update t1 set c2 = null;
alter table T1 modify C2 number(9);
Be aware that ALTER is DDL, which means it performs an implicit COMMIT right before and right after the operation.
If you need to save the data in C2 and convert it to NUMBER you can add a new column, make the conversion, drop the old column, and rename the new column:
alter table T1 add C2_new number(9);
update t1 set c2_new = <your conversion of C2>;
alter table T1 drop column C2;
alter table T1 rename column C2_new to C2;
(don't forget about DDL which you cannot ROLLBACK)
Alter table and add new column with default value via a function in Oracle
I think you can achieve it using the default clause
on the column
but without function
(just replace the function
call with the content of the function
in default
clause) as following. (Please note that the User functions
are not allowed in the default clause
)
ALTER TABLE TEST
ADD ID_NUM VARCHAR(255)
DEFAULT REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5')
NOT NULL;
I have prepared the db<>fiddle demo to show you the error with function
and success without function
.
Cheers!!
Alter table to modify default value of column
Your belief about what will happen is not correct. Setting a default value for a column will not affect the existing data in the table.
I create a table with a column col2
that has no default value
SQL> create table foo(
2 col1 number primary key,
3 col2 varchar2(10)
4 );
Table created.
SQL> insert into foo( col1 ) values (1);
1 row created.
SQL> insert into foo( col1 ) values (2);
1 row created.
SQL> insert into foo( col1 ) values (3);
1 row created.
SQL> select * from foo;
COL1 COL2
---------- ----------
1
2
3
If I then alter the table to set a default value, nothing about the existing rows will change
SQL> alter table foo
2 modify( col2 varchar2(10) default 'foo' );
Table altered.
SQL> select * from foo;
COL1 COL2
---------- ----------
1
2
3
SQL> insert into foo( col1 ) values (4);
1 row created.
SQL> select * from foo;
COL1 COL2
---------- ----------
1
2
3
4 foo
Even if I subsequently change the default again, there will still be no change to the existing rows
SQL> alter table foo
2 modify( col2 varchar2(10) default 'bar' );
Table altered.
SQL> select * from foo;
COL1 COL2
---------- ----------
1
2
3
4 foo
SQL> insert into foo( col1 ) values (5);
1 row created.
SQL> select * from foo;
COL1 COL2
---------- ----------
1
2
3
4 foo
5 bar
Related Topics
Ibm Db2: Generate List of Dates Between Two Dates
Displaying Columns as Rows in SQL Server 2005
Does SQL Server 2008 Support The Create Assertion Syntax
Aggregation with Group by Date in Spark Sql
Cascading Deletes in Postgresql
Sql Server - "For JSON Path" Statement Does Not Return More Than 2984 Lines of JSON String
Postgresql Batch Insert or Ignore
Automatically Create Scripts for All SQL Server Jobs
Select The Last Row in a SQL Table
How to Update SQL Table from Excel Directly
Oracle SQL Merge to Insert and Delete But Not Update
MySQL Procedure to Update Numeric Reference in Previous Rows When One Is Updated
Need to Convert Text Field to Varchar Temporarily So That I Can Pass to a Stored Procedure
Update Multiple Records in Multiple Nested Tables in Oracle
Get Only Date Without Time in Oracle
What Is Wrong with My Update Statement with a Join in Oracle