generated by default as identity for varchar data type in sql - sql

I have a table xx_abc with data existing in the database.
I want to add a column confi_name in this table which is mandatory column.
If i add this column like
ALTER TABLE xx_abc
ADD
( confi_NAME VARCHAR2(2000) NOT NULL);
I am getting an error :
Error report:
SQL Error: ORA-01758: table must be empty to add mandatory (NOT NULL) column
01758. 00000 - "table must be empty to add mandatory (NOT NULL) column"
So I converted it to
ALTER TABLE xx_abc
ADD
( confi_name VARCHAR2(2000) generated by default as identity (START WITH 2, INCREMENT BY 1)
But this is also throwing an error because generated by defaut has to be of int data type. I basically want to make config_name with value which is unique for each row. and i cannot change its data type as well. Any work around ?

First add the column as nullable.
Then update that column with a default value in every row.
Then set the column to be NOT NULL.

As you have mentioned, the table had their values already. If you are going to add another column with "not null" property, make sure that you insert values equal to the number of values(rows) of the previous columns since you had set it to "not null" as its properties. Another way is not to use "not null" first then set the property to "not null" once you have enough values for the column already.

you have to set a default value for the existing rows before adding the constraint.
1)Modify the table
ALTER TABLE xx_abc
ADD
( confi_NAME VARCHAR2(2000));
2)Set default values
update XX_ABC set confi_NAME = 'DEFAULT';
COMMIT;
3)Add the constraint
alter table XX_ABC add check (confi_NAME is not null);

Existing table:
SQL> CREATE TABLE t(A VARCHAR2(10));
Table created.
SQL> INSERT INTO t VALUES('a');
1 row created.
SQL> INSERT INTO t VALUES('b');
1 row created.
SQL> INSERT INTO t VALUES('c');
1 row created.
SQL> COMMIT;
Commit complete.
Add a new column:
SQL> ALTER TABLE t ADD (b VARCHAR2(10));
Table altered.
Update the rows:
SQL> UPDATE t SET b = 'newvalue';
3 rows updated.
Add NOT NULL constraint:
SQL> ALTER TABLE t MODIFY b NOT NULL;
Table altered.
SQL> desc t
Name Null? Type
----------------------------------------- -------- -------------
A VARCHAR2(10)
B NOT NULL VARCHAR2(10)
SQL>

Related

Missing Keyword Error in Oracle SQL Database [duplicate]

I was wondering how can I add an identity column to existing oracle table? I am using oracle 11g. Suppose I have a table named DEGREE and I am going to add an identity column to that.
FYI table is not empty.
You can not do it in one step. Instead,
Alter the table and add the column (without primary key constraint)
ALTER TABLE DEGREE ADD (Ident NUMBER(10));
Fill the new column with data which will fulfill the primary key constraint (unique/not null), e.g. like
UPDATE DEGREE SET Ident=ROWNUM;
Alter the table and add the constraint to the column
ALTER TABLE DEGREE MODIFY (Ident PRIMARY KEY);
After that is done, you can set up a SEQUENCE and a BEFORE INSERT trigger to automatically set the id value for new records.
From Oracle 12c you would use an identity column.
For example, say your table is called demo and has 3 columns and 100 rows:
create table demo (col1, col2, col3)
as
select dbms_random.value(1,10), dbms_random.value(1,10), dbms_random.value(1,10)
from dual connect by rownum <= 100;
You could add an identity column using:
alter table demo add demo_id integer generated by default on null as identity;
update demo set demo_id = rownum;
Then reset the internal sequence to match the data and prevent manual inserts:
alter table demo modify demo_id generated always as identity start with limit value;
and define it as the primary key:
alter table demo add constraint demo_pk primary key (demo_id);
This leaves the new column at the end of the column list, which shouldn’t normally matter (except for tables with a large number of columns and row chaining issues), but it looks odd when you describe the table. However, we can at least tidy up the dictionary order using the invisible/visible hack:
SQL> desc demo
Name Null? Type
-------------------------------- -------- ----------------------
COL1 NUMBER
COL2 NUMBER
COL3 NUMBER
DEMO_ID NOT NULL NUMBER(38)
begin
for r in (
select column_name from user_tab_columns c
where c.table_name = 'DEMO'
and c.column_name <> 'DEMO_ID'
order by c.column_id
)
loop
execute immediate 'alter table demo modify '||r.column_name||' invisible';
execute immediate 'alter table demo modify '||r.column_name||' visible';
end loop;
end;
/
SQL> desc demo
Name Null? Type
-------------------------------- -------- ----------------------
DEMO_ID NOT NULL NUMBER(38)
COL1 NUMBER
COL2 NUMBER
COL3 NUMBER
One thing you can't do (as of Oracle 18.0) is alter an existing column to make it into an identity column, so you have to either go through a process like the one above but copying the existing values and finally dropping the old column, or else define a new table explicitly with the identity column in place and copy the data across in a separate step. Otherwise you'll get:
-- DEMO_ID column exists but is currently not an identity column:
alter table demo modify demo_id generated by default on null as identity start with limit value;
-- Fails with:
ORA-30673: column to be modified is not an identity column
add the column
alter table table_name add (id INTEGER);
create a sequence table_name_id_seq with start with clause, using number of rows in the table + 1 or another safe value(we don't want duplicate ids);
lock the table (no inserts)
alter table table_name lock exclusive mode;
fill the column
update table_name set id = rownum; --or another logic
add a trigger to automaticaly put the id on insert using the sequence(you can find examples on internet, for example this answer)
When you'll fire the create trigger the lock will be released. (it automatically commits).
Also, you may add unique constraint on the id column, it is best to do so.
For Oracle :
CREATE TABLE new_table AS (SELECT ROWNUM AS id, ta.* FROM old_table ta)
remember this id column is not auto incremented

Oracle SQL error "ORA-00984: column not allowed here" when trying to replace a column

This question is not a duplicate from this one because even if the error messages are equal the answers there do not apply to my case.
I need to change a previous PK Id column defined as VARCHAR(36) NOT NULL to an incremental integer value. I'm trying to write a script to do this but when I run the alter table statement it fails with the error on the title.
The table is previously defined as:
CREATE TABLE journal_messages(
ID VARCHAR(36) NOT NULL, -- column to be changed
MESSAGE VARCHAR(2048) NOT NULL,
MESSAGE_TYPE VARCHAR(30) NOT NULL,
MSG_DATE TIMESTAMP NOT NULL,
MODULE_CODE INTEGER NOT NULL
);
ALTER TABLE journal_messages ADD (CONSTRAINT journal_messages_pk PRIMARY KEY (ID));
The script I'm running is:
DELETE FROM JOURNAL_MESSAGES;
ALTER TABLE JOURNAL_MESSAGES DROP COLUMN ID;
CREATE SEQUENCE journal_messages_seq START WITH 1;
ALTER TABLE JOURNAL_MESSAGES ADD (ID NUMBER(10) DEFAULT journal_messages_seq.nextval NOT NULL); -- error happens here
ALTER TABLE journal_messages ADD (
CONSTRAINT journal_messages_pk PRIMARY KEY (ID));
When I try to create a trigger it to update the incremental, it fails with SQL Error [4098] [42000]: ORA-04098: trigger 'TRG_SEQ_JOURNAL_MSG' is invalid and failed re-validation when I try to insert a new tuple:
ALTER TABLE JOURNAL_MESSAGES DROP COLUMN ID;
ALTER TABLE JOURNAL_MESSAGES ADD (ID NUMBER(10) NOT NULL);
create or replace trigger trg_seq_journal_msg
before insert on journal_messages
for each row
begin
:new.id := journal_messages_seq.nextval;
end;
/
INSERT INTO JOURNAL_MESSAGES (message, MESSAGE_TYPE, msg_date, MODULE_CODE) VALUES ('test', 'alteration', CURRENT_TIMESTAMP, '10');
Umm ... not like that, but like this:
once the table is empty, you don't have to drop the column - just modify its datatype
use a trigger to automatically set IDs value
If you were on 12c, you could have used identity column.
SQL> CREATE TABLE journal_messages(
2 ID VARCHAR(36) NOT NULL, -- column to be changed
3 MESSAGE VARCHAR(2048) NOT NULL,
4 MESSAGE_TYPE VARCHAR(30) NOT NULL,
5 MSG_DATE TIMESTAMP NOT NULL,
6 MODULE_CODE INTEGER NOT NULL
7 );
Table created.
SQL> delete from journal_Messages;
0 rows deleted.
SQL> alter table journal_messages modify (id number(10));
Table altered.
SQL> CREATE SEQUENCE journal_messages_seq START WITH 1;
Sequence created.
SQL> create or replace trigger trg_bi_joumes
2 before insert on journal_messages
3 for each row
4 begin
5 :new.id := journal_messages_seq.nextval;
6 end;
7 /
Trigger created.
SQL>
[EDIT: after reading your comment and saw your edition]
That still works OK - I literally copy/pasted your code and got this:
SQL> ALTER TABLE JOURNAL_MESSAGES DROP COLUMN ID;
Table altered.
SQL> ALTER TABLE JOURNAL_MESSAGES ADD (ID NUMBER(10) NOT NULL);
Table altered.
SQL> create or replace trigger trg_seq_journal_msg
2 before insert on journal_messages
3 for each row
4 begin
5 :new.id := journal_messages_seq.nextval;
6 end;
7 /
Trigger created.
SQL> INSERT INTO JOURNAL_MESSAGES (message, MESSAGE_TYPE, msg_date, MODULE_CODE) VALUES ('test', 'alteration', CURRENT_TIMESTAMP, '10')
2 ;
1 row created.
SQL>
As you can see, everything seems to be just fine. Try the following: recompile the trigger and show errors (if any; if so, please, post them here):
SQL> alter trigger trg_seq_journal_msg compile;
Trigger altered.
SQL> show err
No errors.
SQL>

How DB2(v10.5.0.5) add auto increment column to an exists table

I'm trying to add an auto increment column in an existing table of DB2.
DB2 version is v10.5.0.5.
Following is my query:
alter table DB2INST1.AAA_BJ_BOND
ADD COLUMN id INTEGER NOT NULL DEFAULT 0;
ALTER TABLE DB2INST1.AAA_BJ_BOND ALTER COLUMN id
set generated always as identity (start with 1);
but I got following error:
"com.ibm.db2.jcc.am.SqlSyntaxErrorException: ALTER TABLE "DB2INST1.AAA_BJ_BOND"
specified attributes for column "ID" that are not compatible with the existing
column.. SQLCODE=-190, SQLSTATE=42837, DRIVER=4.13.127"
What can I do to solve this problem?
You must drop the column DEFAULT value first.
This is mentioned in the description of SQL0190N:
If SET GENERATED ALWAYS AS (expression) is specified, but the column
is already defined with a form of generation (default, identity, or
expression) and there is no corresponding DROP in the same statement.
ALTER TABLE DB2INST1.AAA_BJ_BOND
ALTER COLUMN id drop default;
ALTER TABLE DB2INST1.AAA_BJ_BOND ALTER COLUMN id
set generated always as identity (start with 1);
Now I have successfully added auto-increasing ID to the table through the following three steps:
ALTER TABLE DB2INST1.AAA_SEAT ADD COLUMN ID INTEGER NOT NULL DEFAULT 0;
ALTER TABLE DB2INST1.AAA_SEAT ALTER COLUMN ID DROP DEFAULT;
ALTER TABLE DB2INST1.AAA_SEAT ALTER COLUMN ID SET GENERATED ALWAYS AS IDENTITY (START WITH 1);

Null values found

I want to insert a not null value. This is a example:
create table time(
a varchar2(9),
b varchar2(9),
c varchar2(9));
table create
insert into time (a,c) values ('qq','ee');
table altered
When I key this:
alter table time
modify b varchar2(9) not null;
This error come out:
alter table time
*
ERROR at line 1:
ORA-02296: cannot enable (DIP0114713.) - null values found
So how I insert a value to a and c column and also column b is not null?
If you don't mention a column in an insert, then it gets the default value. By default, the default value is NULL. You can specify something else:
create table time (
a varchar2(9),
b varchar2(9) not null default 'NO VALUE',
c varchar2(9))
);
EDIT:
To get your alter table to work, update the value first:
update time
set b = 'NO VALUE'
where b is null;
It's not possible.
First you need to update the data in column b and then apply not null constraint.
Update time set b= 'NA' where b is null
go
ALTER TABLE time
ALTER COLUMN b varchar(9) NOT NULL
go
It is possible to create a constraint without it impacting existing rows:
create table test1(
a varchar2(9),
b varchar2(9),
c varchar2(9));
insert into test1 (a,c) values ('qq','ee');
commit;
alter table test1 modify b varchar2(9) not null novalidate;
select * from test1;
A B C
--------- --------- ---------
qq ee
insert into test1 (a,c) values ('qq2','ee2');
ORA-01400: cannot insert NULL into ("SCHEMA1"."TEST1"."B")
However, I would NOT recommend using this, as if you need to create future constraints on the table, it could massively complicate things, since you have "invalid" data in the table.
Far better to take the hit and "fix" the data at the point when you're creating a constraint, rather than shrug your shoulders and leave it for another time - it will come back to bite you (or if not you, some other poor soul who's stuck maintaining the database in the future!) on the bum.

Oracle SQL to change column type from number to varchar2 while it contains data

I have a table (that contains data) in Oracle 11g and I need to use Oracle SQLPlus to do the following:
Target: change the type of column TEST1 in table UDA1 from number to varchar2.
Proposed method:
backup table
set column to null
change data type
restore values
The following didn't work.
create table temp_uda1 AS (select * from UDA1);
update UDA1 set TEST1 = null;
commit;
alter table UDA1 modify TEST1 varchar2(3);
insert into UDA1(TEST1)
select cast(TEST1 as varchar2(3)) from temp_uda1;
commit;
There is something to do with indexes (to preserve the order), right?
create table temp_uda1 (test1 integer);
insert into temp_uda1 values (1);
alter table temp_uda1 add (test1_new varchar2(3));
update temp_uda1
set test1_new = to_char(test1);
alter table temp_uda1 drop column test1 cascade constraints;
alter table temp_uda1 rename column test1_new to test1;
If there was an index on the column you need to re-create it.
Note that the update will fail if you have numbers in the old column that are greater than 999. If you do, you need to adjust the maximum value for the varchar column
Add new column as varchar2, copy data to this column, delete old column, rename new column as actual column name:
ALTER TABLE UDA1
ADD (TEST1_temp VARCHAR2(16));
update UDA1 set TEST1_temp = TEST1;
ALTER TABLE UDA1 DROP COLUMN TEST1;
ALTER TABLE UDA1
RENAME COLUMN TEST1_temp TO TEST1;
Look at Oracle's package DBMS_REDEFINE. With some luck you can do it online without downtime - if needed. Otherwise you can:
Add new VARCHAR2 column
Use update to copy NUMBER into VARCHAR2
Drop NUMBER column
Rename VARCHAR2 column
Here you go, this solution did not impact the existing NOT NULL or Primary key constraints. Here i am going to change the type of Primary key from Number to VARCHAR2(3), Here are the Steps on example table employee.
Take backup of table and Index, Constraints
created table employee_bkp
create table employee_bkp as select * from employee
commit;
Truncate the table to empty it
truncate table employee
Alter the table to change the type
ALTER TABLE employee MODIFY employee_id varchar2(30);
Copy the data back from backup table
insert into employee (select * from employee_bkp)
commit;
Verify