How to create a new sequence starting with the value of another sequence in hsql? - sequence

Database is HSQLDB.
I have an existing sequence, say SEQ1.
Now I want create another sequence SEQ2 that starts with the next value of SEQ1.
I tried
CREATE SEQUENCE SEQ2 START WITH SELECT NEXT VALUE FOR SEQ1;
CREATE SEQUENCE SEQ2 START WITH (SELECT NEXT VALUE FOR SEQ1);
CREATE SEQUENCE SEQ2 START WITH NEXT VALUE FOR SEQ1;
CREATE SEQUENCE SEQ2 START WITH (NEXT VALUE FOR SEQ1);
None of these seem to work however. Is there another way to achieve this in HSQLDB?

This is not currently possible. Only a numeric literal can be used after START WITH or after ALTER SEQUENCE seq RESTART WITH.

Related

How to create auto incrementing table based on a column name?

The title might be a little confusing but I will try explaining here better.
What I want to achieve is:
Create a table with 3 columns (so far so good):
CREATE TABLE StatisticCounter
(
statisticID NUMBER GENERATED ALWAYS as IDENTITY (START with 1000 INCREMENT by 1),
statistikname varchar(255),
counter integer
);
Create a way to call (function, procedure, trigger or something. I will call it function for now) that will increment counter with 1 based on statistikname or statisticid.
The restriction here being: said statistic is an SQL script ran through a cockpit file with a little bit of a different syntax than regular sql (in: out: select, WHERE with variables). I want to put a function or something in this cockpit file, that will run each time the script is run. Which will auto increment the number of times the statistic has been used.
I have no idea what I need (function, procedure, trigger or anything else) and this is why I am writing it a bit vague.
EDIT: I tried with merge but I always get the WHEN NOT MATCHED result executed. Without CAST its the same.
merge into StatisticCounter stc using
CAST((select 1000 id from dual)AS INTEGER) val on (stc.statisticid=val.id)
when matched then
UPDATE StatisticCounter SET counter = counter + 1;
when not matched then
select * from dual;
I found an answer on my own after going through a lot of functions and procedures.
Create table;
Create function;
Call function in file.
The important thing here is that the outside _cockpit file that executes the SQL goes through all OUT parameters for each line the statistic returns as result. This makes the counter go wild - no way to catch END of statistic or beginning. So I made a second _cockpit with only 1 result and attach it to the statistic I want to count.
CREATE TABLE UDX_Table_StatisticCounter(statisticID INTEGER,
StatistikName varchar2(256 char), counter integer);
CREATE OR REPLACE FUNCTION UDX_FUNC_StatisticCounter(datainput IN
VARCHAR2) RETURN VARCHAR2 IS PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE UDX_Table_StatisticCounter SET counter = counter +1 WHERE statisticID=datainput;
COMMIT;
RETURN 'done'; END UDX_FUNC_StatisticCounter;

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.

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.

How Can I solve ORA-04007

I'm using toad for oracle 11g, I tried to alter a sequence using the UI(user interface).
I want to change the currval.
I block with this error :
ORA-04007: MINVALUE cannot be made to exceed the current value
You do not change currval value of pseudocolumn of a sequence directly - its value changes every time you reference nextval pseudocolumn of the sequence. It sounds more like you want to issue an alter sequence statement to change its minvalue parameter.
If the current value of a sequence is less than the minval you are trying to change to, the error will be raised. You have at least two options to get it done:
Recreate a sequence completely with a new value for a minvalue parameter
Change incremet by value, generate a next value , alter minval parameter and then change increment by value back.
Here is an example:
create sequence seq
increment by 1
minvalue 1
sequence SEQ created.
-- trying to change minvalue
alter sequence seq
minvalue 5
SQL Error: ORA-04007: MINVALUE cannot be made to exceed the current value
select seq.nextval
from dual
NEXTVAL
------------
1
-- alter increment by
alter sequence seq
increment by 4
select seq.nextval
from dual
NEXTVAL
----------
5
-- altering minvalue
alter sequence seq
minvalue 5
sequence SEQ altered.
-- change increment by to 1 as it was before
alter sequence seq
increment by 1
sequence SEQ altered.

Oracle - Modify an existing table to auto-increment a column

I have a table with the following column:
NOTEID NUMBER NOT NULL,
For all intents and purposes, this column is the primary key. This table has a few thousand rows, each with a unique ID. Before, the application would SELECT the MAX() value from the table, add one, then use that as the next value. This is a horrible solution, and is not transaction or thread safe (in fact, before they didn't even have a UNIQUE constraint on the column and I could see the same NOTEID was duplicated in 9 different occasions)..
I'm rather new to Oracle, so I'd like to know the best syntax to ALTER this table and make this column auto-increment instead. If possible, I'd like to make the next value in the sequence be the MAX(NOTEID) + 1 in the table, or just make it 800 or something to start out. Thanks!
You can't alter the table. Oracle doesn't support declarative auto-incrementing columns. You can create a sequence
CREATE SEQUENCE note_seq
START WITH 800
INCREMENT BY 1
CACHE 100;
Then, you can create a trigger
CREATE OR REPLACE TRIGGER populate_note_id
BEFORE INSERT ON note
FOR EACH ROW
BEGIN
:new.note_id := note_seq.nextval;
END;
or, if you want to allow callers to specify a non-default NOTE_ID
CREATE OR REPLACE TRIGGER populate_note_id
BEFORE INSERT ON note
FOR EACH ROW
BEGIN
IF( :new.note_id is null )
THEN
:new.note_id := note_seq.nextval;
END IF;
END;
If your MAX(noteid) is 799, then try:
CREATE SEQUENCE noteseq
START WITH 800
INCREMENT BY 1
Then when inserting a new record, for the NOTEID column, you would do:
noteseq.nextval