Add NOT NULL LOB column without default in Oracle - oracle

I am trying to add a CLOB column to a table (change a VARCHAR to a CLOB actually, but it only seems possible by adding a new column, copying and dropping the old). The column should be NOT NULL without a default value (and the table is not empty). How can I achieve this?
My original idea was to create the column with a dummy default, and change that later, but that does not seem possible:
ALTER TABLE foo RENAME COLUMN text TO text_temp;
ALTER TABLE foo ADD (
text CLOB DEFAULT '*' NOT NULL
);
UPDATE foo SET text = text_temp;
ALTER TABLE foo DROP COLUMN text_temp;
ALTER TABLE foo MODIFY (
text CLOB NOT NULL
);
-- ORA-22296: invalid ALTER TABLE option for conversion of LONG datatype to LOB
I also tried defining the column as text CLOB and adding the NOT NULL constraint later, but it gave the same error. Is there a way of doing this, short of recreating the whole table?

Does
ALTER TABLE foo MODIFY text DEFAULT NULL;
work for you?
When adding or removing a default value or a NOT NULL constraint, you don't need to specify the datatype of the column.
EDIT: To quote the Oracle documentation on ALTER TABLE:
If a column has a default value, then you can use the DEFAULT clause to change the default to NULL, but you cannot remove the default value completely. If a column has ever had a default value assigned to it, then the DATA_DEFAULT column of the USER_TAB_COLUMNS data dictionary view will always display either a default value or NULL.
This should explain why you're seeing a difference in SQL Developer.
However, I don't believe there's a significant difference between specifying DEFAULT NULL for a column and not specifying a default value. In both cases, a null value will be assumed for any column not explicitly given a value in an INSERT statement.

You are declaring the column as NOT NULL when you added it to the table, so you don't need to make it NOT NULL again. I think if you corrected the syntax in the final MODIFY clause you would still get an error, albeit a different one (precise number eludes me right now).
But what you are trying to acheive is definitely possible, with the right syntax :)
SQL> alter table t23 add ctxt clob
2 /
Table altered.
SQL> update t23 set ctxt = txt
2 /
2 rows updated.
SQL> alter table t23 modify ctxt not null
2 /
Table altered.
SQL> alter table t23 drop column txt
2 /
Table altered.
SQL> alter table t23 rename column ctxt to txt
2 /
Table altered.
SQL>

Related

Field autoincrement for Oracle without trigger with Slick?

I am trying to insert rows in a ErrorTable which has a few fields plus an idError which is supossed to be the primary key. I need idError to be autoincremented. However one requirement is we cannot use a trigger, so using O.AutoInc would not work for us.
We also tried to use plain sql using a sequence. However we have two blob fields which makes the query too long ( getting the string literal too long error).
Any idea about how to attack this problem? I am also considering to use UUID.
Note: we are using oracle-xe-11g
In 11g you can have only implement an auto-incrementing identifier with a trigger. So it seems your requirements rule out anything except SYS_GUID. Find out more.
" it also represents another query to get that value "
Not necessarily. If you have the option to define the target table you can set a default values for the UUID column like this:
create table t23 (
id raw(16) default sys_guid() not null primary key
, col1 varchar2(10)
);
Then
SQL> insert into t23 (col1) values ('ABC');
1 row created.
SQL> select * from t23;
ID COL1
-------------------------------- -----------
7DD7216E731C126537615FE1244B4B50 ABC
SQL>
Note: tested on 12C but should work in earlier versions.

How to modify data type in Oracle with existing rows in table

How can I change DATA TYPE of a column from number to varchar2 without deleting the table data?
You can't.
You can, however, create a new column with the new data type, migrate the data, drop the old column, and rename the new column. Something like
ALTER TABLE table_name
ADD( new_column_name varchar2(10) );
UPDATE table_name
SET new_column_name = to_char(old_column_name, <<some format>>);
ALTER TABLE table_name
DROP COLUMN old_column_name;
ALTER TABLE table_name
RENAME COLUMN new_column_name TO old_coulumn_name;
If you have code that depends on the position of the column in the table (which you really shouldn't have), you could rename the table and create a view on the table with the original name of the table that exposes the columns in the order your code expects until you can fix that buggy code.
You have to first deal with the existing rows before you modify the column DATA TYPE.
You could do the following steps:
Add the new column with a new name.
Update the new column from old column.
Drop the old column.
Rename the new column with the old column name.
For example,
alter table t add (col_new varchar2(50));
update t set col_new = to_char(col_old);
alter table t drop column col_old cascade constraints;
alter table t rename column col_new to col_old;
Make sure you re-create any required indexes which you had.
You could also try the CTAS approach, i.e. create table as select. But, the above is safe and preferrable.
The most efficient way is probably to do a CREATE TABLE ... AS SELECT
(CTAS)
alter table table_name modify (column_name VARCHAR2(255));
Since we can't change data type of a column with values, the approach that I was followed as below,
Say the column name you want to change type is 'A' and this can be achieved with SQL developer.
First sort table data by other column (ex: datetime).
Next copy the values of column 'A' and paste to excel file.
Delete values of the column 'A' an commit.
Change the data type and commit.
Again sort table data by previously used column (ex: datetime).
Then paste copied data from excel and commit.

Oracle: Changing VARCHAR2 column to CLOB

I have an encountered an issue where the data I was trying to store in my varchar2(4000) column was too big, so I wish to change the column to one more suitable for storing large amounts of textual data. Specifically, a serialized array.
Firstly, is CLOB the best data type for me to use for this purpose? Is there a more appropriate data type?
Secondly, when I try to alter the column using the usual snyntax:
ALTER TABLE table MODIFY column CLOB
I get the following error: ORA-22858: invalid alteration of datatype
What's the most straightforward way to alter this table without losing any data?
The most straightforward way, given that the operation of moving from a varchar column to a CLOB is disallowed, would be to create a new column and move the data from the old column to the new column:
ALTER TABLE some_table ADD (foo CLOB);
UPDATE some_table SET foo = old_column;
ALTER TABLE some_table DROP COLUMN old_column;
ALTER TABLE some_table RENAME COLUMN foo TO old_column;
The VARCHAR2 column cannot be directly converted to CLOB but it can be done in 2 steps:
Convert column datatype from VARCHAR2 to LONG.
Convert column datatype from LONG to CLOB.
ALTER TABLE table MODIFY column long;
ALTER TABLE table MODIFY column clob;
For Oracle 11g:
ALTER TABLE table MODIFY column long;
ALTER TABLE table MODIFY column clob;

Alter table after keyword in Oracle

ALTER TABLE testTable ADD column1 NUMBER(1) DEFAULT 0 NOT NULL AFTER column2;
Why can't I use mySql syntax in Oracle too? The above command works in MySql. Can you give me an equivalent that works?
Error report:
SQL Error: ORA-01735: invalid ALTER TABLE option
01735. 00000 - "invalid ALTER TABLE option"
I am asking if there is any way to use after clause in Oracle command that I provided?
Because SQL is a relational algebra. It doesn't care one bit about "where" columns are located within a table, only that they exist.
To get it to work in Oracle, just get rid of the after clause. The Oracle documentation for alter table is here but it boils down to:
alter table testTable
add ( column1 number(1) default 0 not null )
There is no after clause for the alter table command.
Oracle does not support adding columns in the middle of a table, only adding them to the end. Your database design and app functionality should not depend on the order of columns in the database schema. You can always specify an order in your select statement, after all.
However if for some reason you simply must have a new column in the middle of your table there is a work around.
CREATE TABLE tab1New AS SELECT 0 AS col1, col1 AS col2 FROM tab1;
DROP TABLE tab1 PURGE;
RENAME tan1New to tab1;
Where the SELECT 0 AS col1 is your new column and then you specify other columns as needed from your original table. Put the SELECT 0 AS col1 at the appropriate place in the order you want.
Afterwards you may want to run an alter table statement on the column to make sure it's the data type you desire.
Try this :
ALTER TABLE testTable ADD column1 NUMBER(1) DEFAULT 0 NOT NULL

H2: Adding a NOT NULL column to a table with records

I'd like to add a NOT NULL column to a table called server. Problem is, the table already contains records. When I invoke ALTER TABLE server ADD COLUMN full_discovery_duration BIGINT NOT NULL H2 complains that full_discovery_duration may not be null. I can work around the problem by specifying DEFAULT 0 but I don't want a default valuefor future inserts. What am I supposed to do?
Should I add the column with a default and then remove DEFAULT 0 from the column definition in a subsequent statement? Is there a better way?
You can first add the column with a default value, and then set the default to null. Getting rid of the default definition is not possible however as far as I know.
An alternative is to first allow null, then set the values, and later not allow nulls.
drop table server;
create table server(id int);
insert into server values(1);
alter table server
add column
full_discovery_duration bigint;
update server set full_discovery_duration = 0;
alter table server
alter column
full_discovery_duration set not null;
While adding columns to existing tables, it should either be a nullable column or a default value must be specified. And what do you mean by removing the default? how can you remove value from a not null column?

Resources