reasons behind decreasing of "last value" of a SEQUENCE automatically in postgresql? - postgresql

I am using a "sequence" with start value = 1 and increment = 1 and suppose i insert 10 elements in the table then "last_value" goes to 10. now if i delete 10th element then "last_value" still points to 10. now my question is, is there any possibility that value of "last_value" may decrease to 9 by killing postgres or by taking dump and then again restoring the database (or any other case).
In my case it happened (i don't know how).please provide possible reasons for this.

There are only 2 cases, when a sequence is "decreased":
Sequence reached its MAXVALUE and is reset to MINVALUE . This can be controled with [ NO ] CYCLE in CREATE SEQUENCE
Sequence is explicitly reset with setval()
There are no other ways to get the same value from a sequence 2 times.

You can set the value of a sequence.
SELECT setval('public.sequence_name', 9, true);
However, if you need the values to be contiguous, I'm not sure that a sequence is the most appropriate way to go about that. Perhaps using rank()?

Related

T-SQL set a rotating Flag (True/False) in records using Stored Proc

I can do this using multiple commands in C# for the app I'm creating, but prefer a stored proc to eliminate issues with latency/locks, etc. (hopefully):
I have a table of 10 extensions (important fields):
SortOrder, Extension, IsUsed
First record will be set to IsUsed = true
When calling the stored proc, I need the IsUsed of the NEXT record in sort order to be set to true,the current record that is true set to false. When I hit the last record, rotate back to the first record.
Use Case: I need to rotate through a bank of usable numbers. Multiple people use the app, so cannot reuse. a number within the last 4 minutes (Bank of 10 will suffice, but we can extend if necessary). When the user requests a number, they get the next avail. I can build the table however needed, so any and all options to achieve use case are welcome.
I need to set the flag to true on the 1st record when stored proc is called. All other records should be false.
I have seen this, which is of interest, but doesn't quite answer:
Get "next" row from SQL Server database and flag it in single transaction
If all that you're using this for is to return a number to identify a session, I'd suggest scrapping the whole table idea and letting SQL Server do the work for you.
You can create a SEQUENCE object that will cycle and return the next value for you, without needing to write any code or maintain any tables.
CREATE SEQUENCE dbo.Extension
AS integer
START WITH 5
INCREMENT BY 5
MINVALUE 5
MAXVALUE 50
CYCLE;
This will return the number 5 the first time it's called, up to the number 50 on call number 10, and then start back over. You can adjust the numbers in the code to more or less do whatever you would like, though.
Get the next value like this:
SELECT NEXT VALUE FOR dbo.Extension;
And when/if you need to extend the range:
ALTER SEQUENCE dbo.Extension
MAXVALUE 100;
Play around with the idea on the Rextester demo.
Edit: In light of the comments above and below, I'd still stick with a SEQUENCE, I think.
Every time your code calls the table for an extension, use a query along the lines of this:
SELECT
Extension
FROM
ExtTable
WHERE
SortOrder = NEXT VALUE FOR dbo.Extension;
Functionally, this should do what you're after, again with no code to write or maintain.

Siddhi query for event prior to another within time limit

I am trying to write a Siddhi query to detect if an event didn't happen prior to another within a time limit. The query I have to detect if 'X' didn't ever happen prior to 'Y' in the entire life of the siddhi application is:
from stream[value == 'Y']
and not stream[value == 'X']
I assumed adding a time constraint would work:
from stream[value == 'Y']
and not stream[value == 'X'] for 5 min
However, the 'for' statement never has any effect that I can see. This query is still triggered whether 'X' was 4 minutes ago or 6 minutes ago. I understand that a similar effect can be achieved by checking if 'Y' comes after 'X' within a time limit, but for my purposes I need to know the other way around.
Is this possible with Siddhi? If so can someone please provide a sample query that could achieve this?
Based on your comment I am composing below answer.
Sequence construct in Siddhi will guarantee that no one can enter the state flow at a random point. As an example let's take below sample sequence query.
from every e1=InputStream[state='X'], e2=InputStream[state'Y']
select e1.state as initialState, e2.state as finalState
insert into NextStream;
So in here we are mandating X followed by a consecutive Y. If Y occurs before X sequence construct will handle that and discard Y. So whatever goes into NextStream is guaranteed to satisfy x -> Y state transition.
More relaxed construct of sequence is pattern. It is same as sequence while relaxing the consecutive arrival requirement. Hope this helps!!

No cache in sequence

Could you please help me in the below scenerio
In our application we are using the sequence with no cache. Even though sequence number is not generating with the order. It is resulting with gap in the sequence genearation.Below is the sequence definition.
SEQUENCE_OWNER SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER
DBOWNER SEQUENCENAME 1 1.00000000000000E+27 1 N N 0 145095
How could we achieve sequence number without gap.
Thanks,
Gajendra
Sequence-generated numbers are not designed to be gap-free.
For example, use of a sequence number followed by a rollback will not rollback the use of the sequence number.
If you really do need a gap free number then you'll have to sacrifice concurrency by implementing a locking mechanism while you generate a new number and commit the new row.
Alternatively, if you need high-concurrency, you can leave the value blank and fill it in asynchronously with a batch process.

Postgresql sequences

When I delete all records from a Postgresql table and then try to reset the sequence to start a new record with number 1 when it is inserted, i get different results :
SELECT setval('tblname_id_seq', (SELECT COALESCE(MAX(id),1) FROM tblname));
This sets the current value of the sequence to 1, but the NEXT record (actually the first because there are no records yet) gets number 2!
And I can't set it to 0, because the minimum value in the sequence is 1!
When I use :
ALTER SEQUENCE tblname_id_seq RESTART WITH 1;
the first record that is inserted actually gets number 1 ! But the above code doesn't accept a SELECT as a value instead of 1.
I wish to reset the sequence to number 1 when there are no records, and the first record then should start with 1. But when there ARE already records in the table, I want to reset the sequence so that the next record that is inserted will get {highest}+1
Does anyone have a clear solution for this?
Use the three-argument form of setval to set the is_called flag to false, so that it returns the current value of the sequence for the next nextval call rather than immediately generating a new one.
http://www.postgresql.org/docs/current/interactive/functions-sequence.html
Also note you need to use COALESCE(MAX(id),0)+1, otherwise the first value from the sequence will be MAX(id), which you know to already exist. (thx Stephen Denne)
See http://www.postgresql.org/docs/current/static/functions-sequence.html, near the bottom of the page.
Specifically, at least in Postgresql 9.0, you can find and set the value of a sequence. You can use the three-argument form of setval() to set either the current value of the sequence or the next value of the sequence (which would allow you to set the sequence to 1 on the next value retrieval).

How does a database handle auto-number field if it's limit is reached?

In my tables, i have selected id column to be of type int (4 bytes). The answer i want to know is how will any database handle it once it's limits are reached? Will the database refuse to insert any more records in table? or what exactly will happen? Also how should i tackle this type of problem (if the database doesn't handle it by itself)?
I would love to know what you refer to as "the" database. But usually it is an error. The database is full then. You should provide some means for "compacting" the primary key then, or more easy:
Use long integers as keys (8 bytes). Even if you insert 1000 items per second from now on, this will last for nearly 300 million years. The 4 byte integer (signed) will only last for 24 days in this scenario.