We use a sequence in a Db2 database. Recently, we have migrated the data from an AIX server to a Linux server. During that the latest number of that sequence was not moved to the Linux system. As a consequence, we are seeing duplicates values now.
Here is how we use the sequence:
SELECT NEXTVAL FOR SEQ_YFS_ORDER_NO FROM SYSIBM.SYSDUMMY1
The current value of the sequence on Linux is 100092142. How can I update it to the current value that we have on the AIX system, i.e to (100110960)?
You can modify the sequence using ALTER SEQUENCE. An option offered by ALTER SEQUENCE is to RESTART it with a specific value. Try something like this:
ALTER SEQUENCE SEQ_YFS_ORDER_NO RESTART WITH 100110960
Also note that sequence numbers typically are cached. This may lead to a gap and could have caused the issue during the migration.
Use the below query to fetch next sequence value from DB2 database.
SELECT NEXT VALUE FOR "Sequence_name" FROM SYSIBM.SYSDUMMY1
Work Around
ALTER SEQUENCE SEQ_YFS_ORDER_NO INCREMENT BY (100110960-100092142);
SELECT SEQ_YFS_ORDER_NO FROM dual;
ALTER SEQUENCE SEQ_YFS_ORDER_NO INCREMENT BY 1;
Before backup of your database, you can too create one Stored Procedure to SET "START WITH" with current_value to all your SEQUENCES, so when you will do restore, they will be restored with your desired starts.
Related
In the project I'm working at the Id for certain insert statements is managed by hdbsequences. Now I want to create a sequence for another table that already has existing data in it and I want it to start with the max id value of the data of that table.
I know I could just manually set the "start_with"-Property to it but that is not an option because we need to transport the sequence to another system later where the data in that corresponding table is not the same as on the current system (therefore the ID is different).
I also know of the "reset_by"-Property in which I can select the max value of the table, the problem is that I don't know how to trigger that explicitly.
What I already found out, is that the "reset_by"-Property is called whenever the database is restarted, but unfortunately that is not also not an option because we can't reset the database to not disrupt the other systems.
Thanks in advance for your time and help.
You can do an ALTER SEQUENCE and set the value to be used by the next sequence usage with the option "restart with".
For instance (schema name and sequence name have to be replaced):
alter sequence "<schema name>"."<sequence name>" restart with 100;
The integer value behind the "restart with" option has to be set to the value which has to be used next. So in case your last ID is 100, set it to 101. 101 is the value returned by the next NEXTVAL call on the sequence.
Background: I am migrating from postgreSQL to Vertica and found, that there are some issues in IDENTITY or AUTO_INCREMENT columns. One of these issues is, that vertica cannot assign values to IDENTITY columns or alter a column, that already has data into an IDENTITY column. Therefore I created a sequence and set the default value of the column to be unique doing:
SELECT MAX(id_column) FROM MY_SCHEMA.my_table;
which is 12345
CREATE SEQUENCE MY_SCHEMA.seq_id_column MINVALUE 12346 CACHE 1;
ALTER TABLE MY_SCHEMA.my_table
ALTER COLUMN id_column SET DEFAULT(MY_SCHEMA.seq_id_column.nextval);
ALTER TABLE MY_SCHEMA.log ADD UNIQUE(id_column);
Which works as expected. In this case, I have the cache deactivated, as I am on a single node installation and I want my ID column to be contiguous. However, this is not an option on a cluster installation as the needed lock leads to a bottleneck.
Question: In a vertica cluster with several nodes, how can I access the ID of the last insert in a session (without an additional select)?
E.g. in postgreSQL I could do something like
INSERT INTO MY_SCHEMA.my_table RETURNING id_column;
which does not work in Vertica. Furthermore, the LAST_INSERT_ID() function of Vertica does not work for named sequences. I also feel, that querying the current_value of MY_SCHEMA.seq_id_column could be giving wrong results due to caching, but I am unsure about this.
Why no additional SELECT?
To my knowledge, the select will only give correct values after a commit. I cannot do a commit after every single insert due to performance.
The comments from LukStorms pointed me in the right direction.
The NEXTVAL() function (as far as I have tested) gives contiguous values in the case, where one single session queries them. Furthermore, on concurrent access, if issued after an insert, CURRVAL retrieves the cached value, which is guaranteed to be unique but not necessarily contiguous. As I never call NEXTVAL anywhere else as in my default clause, this solves the problem for me, although there might be cases, where an additional call to NEXTVAL between inserts increments the sequence counter.
One case I can think of (and that I will test in the future) is what happens if AUTO COMMIT is set to OFF, which is ON by default for the vertica client drivers.
UPDATE:
This even seems to work with AUTOCOMMIT being OFF (shown using the vertica-python client driver, where C is the connection and cur the cursor):
cur.execute("SELECT NEXTVAL('my_schema.my_sequence');")
cur.fetchall()
--> 1
cur.execute("SELECT CURRVAL('my_schema.my_sequence');")
cur.fetchall()
--> 1
cur.execute("SET SESSION AUTOCOMMIT TO OFF")
cur.execute("SELECT NEXTVAL('my_schema.my_sequence');")
cur.execute("SELECT NEXTVAL('my_schema.my_sequence');")
cur.execute("SELECT NEXTVAL('my_schema.my_sequence');")
cur.execute("SELECT CURRVAL('my_schema.my_sequence');")
cur.fetchall()
--> 4
However, this seems to be unchanged during a rollback of the connection. So the following happens:
C.rollback()
cur.execute("SELECT CURRVAL('my_schema.my_sequence');")
cur.fetchall()
--> 4
I need to rename bunch of sequences in another schema.
RENAME old_seq to new_seq doesnt work.
Tried:
ALTER SEQUENCE old_seq RENAME TO new_seq;
but it gives me error
ORA-02286: no options specified for ALTER SEQUENCE
I do not wish to mention all the options that i had mentioned earlier while creating the sequence, since they need to be same. Only the name needs to be changed.
If you are not the owner of that sequence, You can use following steps:-
SELECT CURVAL FROM old_seq;
This will give you the value of Current_Sequence.
Now Drop this sequence using
DROP SEQUENCE old_seq;
And Create new Sequence with same name. Using
CREATE SEQUENCE old_seq;
And then alter that with this:-
ALTER SEQUENCE seq_example INCREMET BY <CURVAL FROM OLD VALUE>;
The answer from #ankit is quite in line with what's needed to fix this issue but it presents a few problems and typos which I'm fixing in this answer. I hope it'd be useful.
First, you have to select the current value for the old_seq:
SELECT old_seq.CURRVAL FROM dual;
If you get an ORA-08002 error that's because you need to ask for the NEXTVAL first in order to initialize the sequence. Just do:
SELECT old_seq.NEXTVAL FROM dual;
and then ask for CURRVAL again.
Now that you have the current value, just drop the old sequence by using
DROP SEQUENCE old_seq;
and create the new_seq with the name you want by using
CREATE SEQUENCE new_seq START WITH <CURRVAL FROM old_seq>;
If you use INCREMENT instead of START WITH, you should take into account that the increment would apply to every request for a value from the sequence. You would have to create the sequence and then reset the increment to 1. Using START WITH avoids that issue.
You can rename it straight out:
rename old_sequence to new_sequence;
It would say table renamed but you can ignore it. Your sequence will be renamed.
Try it.
Suppose SEQUENCE starts from "1", today it generated some sequences then on next day it should again start from "1".
Is it possible or need to find any workaround ?
Yes: You can schedule a job to recreate the sequence.
Read here: http://docs.oracle.com/cd/E11882_01/server.112/e25494/scheduse002.htm
Depends totally on your database product. Default SQL has no such thing. You need to have some periodic call to the database to reset the value.
You can use a CRON Job which can fire following command(In case you are using MySQL) at noon.
ALTER TABLE table_name AUTO_INCREMENT= 1;
I recently created a SQL dump of a database behind a Django project, and after cleaning the SQL up a little bit was able to restore the DB and all of the data. The problem was the sequences were all mucked up. I tried adding a new user and generated the Python error IntegrityError: duplicate key violates unique constraint.
Naturally I figured my SQL dump didn't restart the sequence. But it did:
DROP SEQUENCE "auth_user_id_seq" CASCADE;
CREATE SEQUENCE "auth_user_id_seq" INCREMENT 1 START 446 MAXVALUE 9223372036854775807 MINVALUE 1 CACHE 1;
ALTER TABLE "auth_user_id_seq" OWNER TO "db_user";
I figured out that a repeated attempt at creating a user (or any new row in any table with existing data and such a sequence) allowed for successful object/row creation. That solved the pressing problem.
But given that the last user ID in that table was 446 - the same start value in the sequence creation above - it looks like Postgresql was simply trying to start creating rows with that key.
Does the SQL dump provide the wrong start key by 1? Or should I invoke some other command to start sequences after the given start ID? Keenly curious.
The dump is fine, no problem. If your code (or default value for the column) uses nextval() to get the next value from the sequence, everything will be fine as well. Check your code and see what it does, what SQL is executed. With this information you can see why things are going wrong.
Good luck!