Insert into a sequence? - sql

Does this SQL make sense?
CREATE SEQUENCE order_id_sequence
START WITH 310;
INSERT INTO order_id_sequence VALUES (150);

The way you'd usually use a sequence is to select the next sequential value from it:
SELECT ORDER_ID_SEQUENCE.NEXTVAL FROM DUAL;
Or in PL/SQL you can just assign the next value to a variable:
DECLARE
nSeq_value NUMBER;
BEGIN
nSeq_value := ORDER_ID_SEQUENCE.NEXTVAL;
-- ...etc etc etc...
END;
It is possible to alter a sequence to change the minimum value:
ALTER SEQUENCE ORDER_ID_SEQUENCE MINVALUE 150;
However, if you want to change the 'next' value returned by the sequence the only way to do it is to drop the sequence and recreate it.
Share and enjoy.

Not a validate one. You can try it in a testing env.
In fact, test it by yourself is a good way before asking question here.

Related

how to define a trigger that gives id automatically when insert a new person?

as I described on the title, I want to write a trigger that defines to add a new staff by all giving attributes except ID, I want to trigger generate and insert it automatically. How can I do that?
I've written a code like below in PL/SQL, but it's including the sequence and I couldn't find how can I get the current max ID of my staff with using the sequence, so could you please help me, with or without using the sequence?
CREATE SEQUENCE BEFORE_INSERTING START WITH 1000 INCREMENT BY 1;
CREATE OR REPLACE TRIGGER NEW_ID_BEFORE_INSERTING
BEFORE INSERT ON STAFF
FOR EACH ROW
BEGIN
:NEW.STAFF_ID := BEFORE_INSERTING.nextval;
END;
/
By the way, this code works fine but as you see it's starting from 1000.
Perhaps you can use something like the following to find the maximum value for STAFF_ID and then redefine the sequence based on that value:
DECLARE
nMax_staff_id NUMBER;
BEGIN
SELECT MAX(STAFF_ID)
INTO nMax_staff_id
FROM STAFF;
EXECUTE IMMEDIATE 'DROP SEQUENCE BEFORE_INSERTING';
EXECUTE IMMEDIATE 'CREATE SEQUENCE BEFORE_INSERTING START WITH ' ||
nMax_staff_id + 1 || ' INCREMENT BY 1';
END;
You only need to run the above once, just to get the sequence reset. After that the trigger will use the sequence to obtain each STAFF_ID value. Note that there are other ways to redefine a sequence's value, but here we'll do The Simplest Thing That Could Possibly Work, which is to drop the sequence and then recreate it with the new starting value.
Best of luck.
in order to find the max STAFF_ID you need the below select:
select max(STAFF_ID) from STAFF;
Once you have the highest STAFF_ID you can re-create the sequence as desired.
In any case you can increment a sequence like so:
ALTER SEQUENCE seq_name INCREMENT BY 1;
I hope that helps!
Please don't hesitate to leave a comment for any further clarifications.
Ted.
Using the sequence guarantees uniqueness of STAFF_ID but does not guarantee no gaps in assigning STAFF_ID. You might end up with STAFF_ID like 100, 101, 103, 106..
First, get the max(STAFF_ID) while the system is not running. Something like
select max(staff_id) from staff;
Then, create the sequence to start from the max staff_id. Something like
create sequence staff_sequence start with <max_id> + 1 increment by 1 nocache;
"NOCACHE" minimizes the chance of having gaps in the staff_id assigned
After, use the trigger that you created to get the nextval from the seuqnece
Note the following:
- Once a sequence is invoked for nextval, that number dispatched cannot be returned to the sequnece
- Any cached sequence values will be lost if oracle database was shutdown
If your requirement is not to have gaps between staff_ids, then sequence might not be used.

oracle 11g - what is the way to get the last inserted id of the identity column in oracle 11g database?

What is the best way to get the last inserted id of the identity column in oracle 11g database?
I have tried using the following methods:
SEQUENCE objects
manually defining a function/stored procedure for getting the last inserted ID value
But none of these approaches don't seem to be useful for my use case.
Please suggest other methods for the same
Can it help you?
SELECT last_number
FROM user_sequences
WHERE sequence_name = '<sequence_name>';
do you want to get last sequence number or last inserted?
I hope this will help you
SELECT MAX(column_name)
FROM table_name
WHERE condition;
Oracle has a very cool feature in which we can use RETURNING clause where we can get the last inserted/updated data. Hope below snippet helps.
CREATE SEQUENCE avr_seq START WITH 1 INCREMENT BY 1;
SET serveroutput ON;
DECLARE
lv_id PLS_INTEGER;
BEGIN
INSERT INTO AV_TEST VALUES
(avr_seq.NEXTVAL
) RETURNING TEST INTO lv_id;
dbms_output.put_line(lv_id);
END;
/
If i have understand well the question, just do this
SELECT max(id_column) from your_table;

update increment of serial field from several records in postgres

I want to change the increment value of all my columns that use sequencial IDs. How can I do it?
I tried the following 2 approaches, both failed:
UPDATE information_schema.sequences SET increment=1;
This doesn't work because information_schema.sequences it's a view.
I also tried to use ALTER SEQUENCE, adding a FROM at the end, like:
ALTER SEQUENCE A.sequence_name INCREMENT BY 2 FROM (SELECT * FROM information_schema.sequences) AS A
But I get a syntax error.
How can I do this?
Try using setval from docs
OR
ALTER SEQUENCE... RESTART WITH... as described here
EDITED TWICE
Sample how to change all sequences in owned schema:
do
$$
declare
i record;
begin
for i in (select * from information_schema.sequences) loop
execute $e$ALTER SEQUENCE $e$||i.sequence_name||$e$ INCREMENT BY 2$e$;
end loop;
end;
$$
;
DO

how auto generate number start from specific number the first 4 # include the current year in oracle 11g

i have table which have id when iwnna to insert new record its by default generate new # increment by 1 how can i do it please
the number is begin with year and serial for ex; 20130001,20130002,20130003 and so on , when the year is end then will start 20140001,20140002,20140003
Putting aside the question why you would want to do this.
The most straightforward approach is to create an Oracle SEQUENCE object, starting at the value you want to start with, increment of 1. As an example:
CREATE SEQUENCE myseq START WITH 20130001 INCREMENT BY 1 NOCACHE ;
To make use of the sequence object to supply a value for a table on an INSERT, create a BEFORE INSERT trigger
CREATE TRIGGER mytable_trg_bi
BEFORE INSERT ON mytable
FOR EACH ROW
BEGIN
IF NEW.mycol IS NULL THEN
SELECT myseq.NEXTVAL FROM DUAL INTO NEW.mycol;
END IF;
END;
/
(It's been a while since I've worked with the Oracle syntax; some of the keywords might not be in the right order. But this is the normal pattern for assigning unique, system generated values to a column on an INSERT.
That part is easy.
The trickier part is getting the sequence to "jump" to a specific value.
There's a couple of approaches to doing that. One would be drop the sequence object and re-create a new object, with the same name, with a new starting value. But that's not very elegant, and fairly disruptive.
Another approach is to modify the increment value, select nextval to make it jump, and then set the increment back to 1.
As a rough outline of what that might look like:
DECLARE
ln_val NUMBER;
BEGIN
-- retrieve next value from sequence
SELECT myseq.NEXTVAL FROM DUAL INTO ln_val;
-- set increment so next call to nextval will "jump"
EXECUTE IMMEDIATE
'ALTER SEQUENCE myseq INCREMENT BY '|| 20140001 - 2 - ln_val ||' NOCACHE';
-- this should return us 20140000
SELECT myseq.NEXTVAL FROM DUAL INTO ln_val;
-- reset increment back to 1
EXECUTE IMMEDIATE
'ALTER SEQUENCE myseq INCREMENT BY 1';
END;
/
Note that this approach of setting/resetting the current value of the sequence is subject to a race condition, if another session is pulling values from the SEQUENCE at the same time.

Same seq_name.nextval in one query. ORACLE

how can you select the same sequence twice in one query?
I have googled this and just cant get an answer.
Just to be clear, this is what I need, example :
select seq.nextval as v1, seq.nextval as v2 from dual (I know that doesn't work)
I have tried UNION as well, Just cant get my head around it.
If you always need exactly two values, you could change the sequence to increment by 2:
alter sequence seq increment by 2;
and then select the current value and its successor:
select seq.nextval,
seq.nextval + 1
from dual;
Not pretty, but it should do the job.
UPDATE
Just to clarify: the ALTER SEQUENCE should be issued only once in a lifetime, not once per session!
The Answer by Frank has a downside:
You cannot use it in transactional system, because the ALTER SEQUENCE commits any pending DML.
The Answer of Sean only pulls the sequence once.
As I understand, you want to pull two values.
As an alternative to Seans solution, you could also select two times from .nextval, due ORACLE gives you the same value twice.
I'd prefer wrapping up the sequence in a procedure.
This tricks oracle to pulling the sequence twice.
CREATE or replace FUNCTION GetSeq return number as
nSeq NUMBER;
begin
select seq.nextval into nSeq from dual;
return nSeq;
end;
/
If you need this generically, maybe you'd like:
CREATE or replace FUNCTION GetSeq(spSeq in VARCHAR2) return number as
nSeq NUMBER;
v_sql long;
begin
v_sql:='select '||upper(spSeq)||'.nextval from dual';
execute immediate v_sql into nSeq;
return nSeq;
end;
/
There are some limitations on how NEXTVAL can be used. There's a list in the Oracle docs. More to the point, the link includes a list of conditions where NEXTVAL will be called more than once.
The only scenario named on the page where a straight SELECT will call NEXTVAL more than once is in "A top-level SELECT statement". A crude query that will call NEXTVAL twice is:
SELECT seq.NEXTVAL FROM (
SELECT * FROM DUAL
CONNECT BY LEVEL <= 2) -- Change the "2" to get more sequences
Unfortunately, if you try to push this into a subquery to flatten out the values to one row with columns v1 and v2 (like in your question), you'll get the ORA-02287: sequence number not allowed here.
This is as close as I could get. If the query above won't help you get where you want, then check out the other answers that have been posted here. As I've been typing this, a couple of excellent answers have been posted.
Telling you to just call sequence.nextval multiple times would be boring, so here's what you can try:
create type t_num_tab as table of number;
CREATE SEQUENCE SEQ_TEST
START WITH 1
MAXVALUE 999999999999999999999999999
MINVALUE 1
NOCYCLE
CACHE 100
NOORDER;
create or replace function get_seq_vals(i_num in number) return t_num_tab is
seq_tab t_num_tab;
begin
select SEQ_TEST.nextval
bulk collect into seq_tab
from all_objects
where rownum <= i_num;
return seq_tab;
end;
And you can use it as follows. This example is pulling 7 numbers at once from the sequence:
declare
numbers t_num_tab;
idx number;
begin
-- this grabs x numbers at a time
numbers := get_seq_vals(7);
-- this just loops through the returned numbers
-- to show the values
idx := numbers.first;
loop
dbms_output.put_line(numbers(idx));
idx := numbers.next(idx);
exit when idx is null;
end loop;
end;
Also note that I use "next" instead of first..last as its possible you may want to remove numbers from the list before iterating through (or, sometimes a sequence cache can results in numbers incrementing by more than 1).
These are all great answers, unfortunately it was just not enough. Will definitely be able to return to this page when struggling in the future.
I have gone with a different method. Asked a new question and got my answer.
You can go check it out here.