I have the following table called table_1
I create a new column_3
then I create a sequence
CREATE SEQUENCE "sequence_1" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOPARTITION
and I alter the table_1 so the default for new values on column_3 are the the values of the sequence.
ALTER TABLE table_1 MODIFY column_3 DEFAULT sequence_1.NEXTVAL
How can I replace the existing null values on column_3 with the values from this sequence? The final result should be:
If your DB version is 12c+, then adding an identity column will handle what's needed such as
ALTER TABLE table_1 ADD new_id INT GENERATED ALWAYS AS IDENTITY
where
using GENERATED and AS IDENTITY are mandatory
There are three following options [ ALWAYS | BY DEFAULT [ ON NULL ] ].
A value for the identity column is always generated if the ALWAYS option is used as in this case. Attempt to insert a value into the identity column will cause an error.
No need to use START WITH and INCREMENT BY options for the
current case. Since those are already 1 as default
Demo
Solution I came up with is the following - happy to accept better answers:
ALTER TABLE table_1 ADD column_3 NUMBER(38,0) DEFAULT sequence_1.NEXTVAL NOT NULL
Related
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
How can I have a primary key that auto increments?
for example: when I insert something at the field name, the field id should be assign a value that is +1 that the last one.
id, name
1, test1
2, test2
so I insert the name something like testX and the id should be auto assigned as 3
how can i do that?
In addition to answer of ain, you can use generator like :
Create a generator :
CREATE GENERATOR <name>;
SET GENERATOR <name> TO <value>;
Getting the current value of generator:
SELECT GEN_ID( <GeneratorName>, 0 ) FROM RDB$DATABASE;
Generating the next value
SELECT GEN_ID( <GeneratorName>, 1 ) FROM RDB$DATABASE;
Using generator in trigger
CREATE OR ALTER trigger <trigger_name>_bi for <table_name>
active before insert position 0
as
begin
if (new.id is null) then
new.id = gen_id(my_generator,1);
end
If you want numeration without holes you have to be very careful.
Generators/Sequences are non-transactional.
Once you get a value if your operation fails, you will have a hole.
If you're using Firebird 3 then you can use the identity column feature:
create table T (
id integer generated by default as identity primary key,
...
);
If you're using some older version of Firebird, then using an sequence with trigger can be used to achieve the autoincrement:
create table T (
id integer primary key,
...
);
CREATE SEQUENCE t_seq;
create trigger t_gen_id
active before insert
on T
as
begin
if(new.id is null)then new.id = next value for t_seq;
end;
Since Firebird 2 the returning clause is supported which is very handy to get the id value generated on the server side.
The use of SERIAL datatype is to auto increment the value, so there is no need to specify the value during insertion of values. If we create a
table and insert value to that table, by default values starts from 1 for SERIAL column datatype. But Instead of 1 is there any way to start the value from 100 and increment by 10 as default value?
Serial is just syntactic sugaring on top of an int column that takes its value from a sequence. While you can't control a serial column's definitions directly, you could use an explicit sequence definition instead:
CREATE SEQUENCE tablename_colname_seq INCREMENT BY 10 START WITH 100; -- Here!
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
You can alter your existing sequence(not matter whether its serial or what) like below
ALTER SEQUENCE mytbl_id_seq INCREMENT 10 RESTART with 100
When creating a table
create table mytbl (id serial,val int)
a sequence will automatically creates i.e
CREATE SEQUENCE mytbl_id_seq
INCREMENT 1
START 1
so you can alter this with your desired values i.e
ALTER SEQUENCE mytbl_id_seq
INCREMENT 10
RESTART with 100
sqlfiddle-demo
I have like 11 columns in my database table and i am inserting data in 10 of them. i want to have a unique number like "1101 and so on" in the 11th column.
Any idea what should i do?? Thanks in advance.
SQL Server 2012 and above you can generate Sequence
Create SEQUENCE RandomSeq
start with 1001
increment by 1
Go
Insert into YourTable(Id,col1...)
Select NEXT VALUE FOR RandomSeq,col1....
or else you can use Identity
Identity(seed,increment)
You can start the seed from 1101 and increment the sequence by 1
Create table YourTable
(
id INT IDENTITY(1101,1),
Col varchar(10)
)
If you want to have that unique number in a different field then you can manipulate that field with primary key and insert that value.
If you want in primary key value, then open the table in design mode, go to 'Identity specification', set 'identity increment' and 'identity seed' as you want.
Alternatively you can use table script like,
CREATE TABLE Persons
(
ID int IDENTITY(12,1) PRIMARY KEY,
FName varchar(255) NOT NULL,
)
here the primary key will start seeding from 12 and seed value will be 1.
If you have your table definition already in place you can alter the column and add Computed column marked as persisted as:
ALTER TABLE tablename drop column column11;
ALTER TABLE tablename add column11 as '11'
+right('000000'+cast(ID as varchar(10)), 2) PERSISTED ;
--You can change the right operator value from 2 to any as per the requirements.
--Also replace ID with the identity column in your table.
create table inc
(
id int identity(1100,1),
somec char
)
I have a table that auto-increments its primary key. How can I return what this value currently is using SQL in HSQLDB?
I found this answer, but it doesn't give a full explanation of how to get it from a specific table.
If the primary key column is declared as IDENTITY, then I don't see a way to get the current value, except for calling the IDENTITY() as described in the other answer, which doesn't give the answer for the specific table.
An alternative is to create the primary key column to use a specific sequence generator instead of IDENTITY. You can then select the current value of the sequence from the INFORMATION_SCHEMA.SEQUENCE table.
The sample below shows how this would work.
create sequence test_seq;
create table test (
id integer generated by default as sequence test_seq,
value varchar(10));
insert into test (value) values ('foo');
insert into test (value) values ('bar');
insert into test (value) values ('bash');
select * from test;
id value
0 'foo'
1 'bar'
2 'bash'
select next_value from information_schema.sequences where sequence_name = 'TEST_SEQ'
3