oracle/sql Creating a sequence without triggering - sql

I created a sequence with beginning value as 2.
create sequence seq_ben
start with 2
increment by 1
nocache
nocycle;
when i was asked to show the next two numbers of the sequence i wrote
select seq_ben.nextval from dual
and ran this code twice to give next two values, then i was asked to show the next sequence without triggering it to move the next number and Use its next three values to add new rows to the the above sequence. Is this possible ? how can it generate a next sequence without triggering it?

You can use CURRVAL, if you have referenced NEXTVAL at least once in the current session.
However, I believe that if you really want to know the next number in the sequence, there is something fundamentally wrong about your design. Sequences are design such that NEXTVAL is an atomic operation, and no two sessions may get the same number. Or an incrementing unique identifier, in other words. That's the only guarantee it gives you. With this design, it is almost meaningless to ask for the next possible value of a sequence.
You may try to use MAX(), which is often used as a poor man's solution to sequences.

Related

Write to the same row at the same time without locking?

What I need to do is to write to the same row from two different sources (procedures/methods/services).
The first call that comes in creates the row, and the next one just updates it.
This needs to happen without any locking taking place. And if possible I would like to be able to call either source just once (not repeatedly by dealing with locking errors)
Here is kinda what I have now in a third procedure that the others call and just inserts a row (only inserts into the xyz) or returns true if there is a row.
That way it´s just fast and unlikely that both calls arrive at the same time.
IF EXISTS(SELECT * FROM [dbo].[Wait] WHERE xyx= #xyz)
BEGIN
-- The row exists because the other datasource
-- has allready inserted a row with the same xyz
-- UPDATE THE ROW WITH DATA COMING IN
END
ELSE
BEGIN
-- No row with value xyz exists so we INSERT it with
-- the extra data.
END
I know it does´t guaranty no lock. But in my case it´s actually unlikely that both arrive at the same time and even if they would it´s user controlled so they will get an error and will just try again. BUT I wan´t to solve this.
I have been seeing Row Versioning popping up but I´m not sure if that helps or how I should use it.
Have a look at Michael J Swarts' article Mythbusting: Concurrent Update/Insert Solutions. This will show you all possible do's and don'ts. Including the fact that merge actually doesn't do a great job in solving concurrency issues.

SQL increment infrequently incorrect

I am trying to maintain a ticketing system to keep track of Work Order numbers and every so often the count of the WO_NUM jumps. The WO_NUM should be the same as the WOID. But for some reason, after using this system for years, the WO_NUM started to be 1 greater than the WOID.
The count for WO_NUM jumps by 2 instead of 1 from WO_NUM 229912 to WO_NUM 229914
Then a few months later (128 days) to be exact, it jumps again this time to 2 greater than the WOID.
The count for WO_NUM jumps from 239946 to 239948
This happens again 18 days later, but this time to 3 greater than WOID with WO_NUM jumping from 241283 to 241285 while WOID increments normally from 241281 to 241822
And again 7 days later to 4 greater than WOID with WO_NUM jumps from 241897 to 241899 while WOID increments normally from 241894 to 241895.
This seems to keep getting further and further off and it his happening almost exponentially quicker. Any idea why this might be/how I might go about fixing it?
If you are using an IDENTITY field in SQL Server or a similar auto-increment mechanism in another system, there is no guarantee that your IDs will be consecutive. If you try to insert a new row and the insert fails, the ID that would have been used is skipped. This is to allow another insert to begin while the other is in process without an ID collision.
If you need (not want) IDs to be consective then you'll have do do something like:
Create a locking mechanism so that inserts are atomic.
Use a key table that will store the next available ID for your table
Only increment the key table if the insert succeeds.
That said, obviously this adds a lot of risk to your system, and doesn't address what happens if you delete a record. I would reconsider whether you need consecutive IDs and whether that feature is worth the extra development and overhead.
figured it out myself. Turns out that if a work order was started and then cancelled without being saved WO_NUM was being incremented and not rolled back. Thanks to all that tried to help, sorry I didn't provide the requisite information. I'll make sure to do better next time!

Is it possible to increment a postgresql entry even if it doesn't exist?

As it says on the tin. I'm looking for something like Redis' INCR, except I also would like to then query for all the item where count is greater than 1.
I'm anticipating a 20-30 gigabytes of data, otherwise I'd just do it in-memory.
You can use the PostgreSQL's Sequence:
CREATE SEQUENCE serial START 1;
SELECT nextval('sequence_name');
Also, take a look at this second answer: next available record id

Invalid numbers on sequence

When I created a sequence for a table article, it's started from 17 not 1
CREATE SEQUENCE seq_article START WITH 1 INCREMENT BY 1;
CREATE OR REPLACE TRIGGER auto_article BEFORE insert ON article
FOR EACH ROW
BEGIN
SELECT seq_article.NEXTVAL INTO :NEW.id_article FROM dual;
END;
/
I tried to delete all rows and creat other data, this time it's started from 19. How can I fix that?
I'm not sure that I understand the problem.
A sequence generates unique values. Unless you set the sequence to CYCLE and you exceed the MAXVALUE (not realistically possible given the definition you posted) or you manually reset the sequence (say, by setting the INCREMENT BY to -16, fetching a nextval, and then setting the INCREMENT BY back to 1), it won't ever generate a value of 1 a second time. Deleting the data has no impact on the next id_article that will be generated.
A sequence-generated column will have gaps. Whether because the sequence cache gets aged out of the shared pool or because a transaction was rolled back, not every value will end up in the table. If you really need gap-free values, you cannot use a sequence. Of course, that means that you would have to serialize INSERT operations which will massively decrease the scalability of your application.

When would you ever set the increment value on a database identity field?

Given the table:
CREATE TABLE Table1
(
UniqueID int IDENTITY(1,1)
...etc
)
Now why would you ever set the increment to something other than 1?
I can understand setting the initial seed value differently. For example if, say, you're creating one database table per month of data (e.g. Table1_082009, Table1_092009) and want to start the UniqueID of the new table where the old one left off. (I probably wouldn't use that strategy myself, but hey, I can see people doing it).
But for the increment? I can only imagine it being of any use in really odd situations, for example:
after the initial data is inserted, maybe later someone will want to turn identity insert on and insert new rows in the gaps, but for efficient lookup on the index will want the rows to be close to each other?
if you're looking up ids based directly off a URL, and want to make it harder for people to arbitrarily access the other items (for example, instead of the user being able to work out that changing the URL suffix from /GetData?id=1000 to /GetData?id=1001, you set an increment of 437 so that the next url is actually /GetData?id=1437)? Of course if this is your "security" then you're probably already in trouble...
I can't think of anything else. Has anyone used an increment that wasn't 1, and why? I'm really just curious.
One idea might be using this to facilitate partitionnement of data (though there might be more "automated" ways to do that) :
Considering you have two servers :
On one server, you start at 1 and increment by 2
On the other server, you start at 2 and increment by 2.
Then, from your application, your send half inserts to one server, and the other half to the second server
some kind of software load-balancing
This way, you still have the ability to identify your entries : the "UniqueID" is still unique, even if the data is split on two servers / tables.
But that's only a wild idea -- there are probably some other uses to that...
Once, for pure fun, (Oh yeah, we have a wild side to us) decided to negative increment. It was strange to see the numbers grow in size and smaller in value at the same time.
I could hardly sit still in my chair.
edit (afterthought):
You think the creator of the IDENTITY was in love with FOR loops? You know..
for (i = 0; i<=99; i+=17)
or for those non semi-colon folks out there
For i = 0 to 100 step 17
Only for entertainment. And you have to be REALLY bored.