Oracle Sequence nextval is jumping number back and forth - c#

I created a new table and a new sequence, I have two C# web services trying to insert records into this table using same query utilizing mySequence.nextval (and yes I checked it many times, they both use mySequence.nextval).
The two web services are inserting rows to the table, but the mySequence.nextval is returning numbers out of sequence
Here is how the records were created, showing PrimaryKey which gets its value from mySequence.nextval
1 21 22 23 2 3 24 25 4 27 28 5
So far no duplicates but why is mySequence.nextval jumping back and forth? and should I worry about it
Update:
The sequence is created with cache_size = 20

I will wager that your database is running RAC (Real Application Clusters). Assuming that is the case and that you create the sequence with all the default settings, that's the expected behavior.
The default setting is to cache 20 values. Each node in the RAC cluster, by default, will have a separate cache. Assuming that you have a cluster with two nodes A and B, the first time a nextval is requested on A, A will cache values 1-20 and return a value of 1. If the next request for a nextval is made on B, B will cache values 21-40 and return a value of 21. From there, the value you get will depend on the node that your connection happens to be running on.
Generally, this shouldn't be a problem. Sequences generate unique numbers. The numbers generally need not be consecutive. If you really need values to be returned sequentially because you are doing something like ordering by the sequence-generated value to determine the "first" or "last" row, you can use the ORDER clause when you create the sequence to force values to be returned in order. That has a negative performance implication in a RAC database, however, because it increases the amount of communication that needs to go on between the nodes to synchronize the values being returned. If you need to determine the "first" or "last" row, it's generally better to add a date or a timestamp column to the table and order by that rather than assuming that the primary key is generated sequentially.

From the docs...
Sequence numbers are generated independently of tables, so the same sequence can be used for one or for multiple tables. It is possible that individual sequence numbers will appear to be skipped, because they were generated and used in a transaction that ultimately rolled back. Additionally, a single user may not realize that other users are drawing from the same sequence.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6015.htm#SQLRF01314

Related

Make Sequence Column Increment Based On Conditions?

Background Information
So here is the background to this question. Currently we have multiple bill of material number identifiers( UNPN,UDEN,UXXN,etc.) Each with its own sequence number (UNPN0001,UNPN0002,UNPN0003,etc.)
When a user requests a new bill of material number, lets say a new UNPN number. If the last number was UNPN0003 then the user should be able to reserve UNPN0004.
My Initial Thought:
So initially I figured, I could simply create a sequence column in a table. So if we had a UNPN table, we could easily add a new record and sequence it automatically and return the combination of UNPN + Generated Sequence number.
The Problem:
So the problem I identified is that for this method, we currently have 50+ different bill of material identifiers. So this would mean I would have to create 1 table for each identifier with its own auto sequence column.
What I am looking for:
I would prefer to avoid creating 50+ different tables. I am not sure if there is a different schema I could use for my database or if I should abandon this method all together for something else. I don't believe you can have multiple sequence columns in a table that only sequence based on what is input, of course I don't have a full understanding of what all is possible
Any suggestions would be appreciated.
Thank you,
You've indicated that you are using Oracle. Oracle has a database level objects known as sequences made for this sort of thing. They are very performant. You would want to make one sequence for each of your identifiers. You only need to do this once for each identifier.
CREATE SEQUENCE UNPN; -- Starts a 1 by default
CREATE SEQUENCE UDEN START WITH 50;
CREATE SEQUENCE UXXN MAXVALUE 9999 CYCLE; -- This one will recycle back to 0001 after it hits 9999
Next when ever you need a new value for a given sequence you can just select it:
SELECT 'UNPN'||TO_CHAR(UNPN.NEXTVAL,'FM0000') FROM DUAL;
To make it easier/more dynamic you can define a function to get the new value by name:
create or replace function get_named_seq(p_sequence varchar2) return varchar2
is
l_sql VARCHAR2(4000);
l_Result varchar2(30);
begin
select 'select '''||sequence_name||'''||to_char('||sequence_name||'.nextval,''FM0000'') from dual'
into l_sql
from user_sequences
where sequence_name = upper(p_sequence);
execute immediate l_sql
into l_Result;
return l_result;
end;
/
The above function will throw a NO_DATA_FOUND exception if the requested sequence doesn't exist, and even though it's using dynamic SQL it should be safe from SQL Injection since the actual dynamic SQL statement never directly touches the input parameter. you would use it like this or any where you can use a function:
INSERT into MyTable (ID, Data) values (get_named_seq('UXXN'), 'some data');

Generating Unique & Randon codes in SQL Server and .NET

I have a requirement to generate a semi-random code in C#/ASP.NET that has to be unique in the SQL Server database.
These codes need to be generated in batches of up to 100 codes per run.
Given the requirements, I'm not sure how I can do this without generating a code and then checking the database to see if it exists, which seems like a horrible way of doing it.
Here are the requirements:
Maximum 10 characters long (alpha-numeric only)
Must not be case sensitive
User can specify an optional 3 character prefix for the code
Must not violate 2 column unique constraint in the database, i.e. must be a unique "code text" within the "category" (CONSTRAINT ucCodes UNIQUE (ColumnCodeText, ColumnCategoryId))
So, given the 10 character limit, GUIDs are not an option. Given the case insensitivity requirement, the mathematical probability for database collisions are fairly high, I think.
At the same time, there are enough possible combinations that a straight look-up table in the DB would be prohibitive, I believe.
Is there a reasonably performant way of generating codes with these requirements that doesn't involve saving them to the DB one code at a time and waiting for a unique key violation to see if it goes through?
You have two options here.
You generate a new ID and insert it. If it throws dup unique key exception then try again until you succeed or bail if you run out of IDs. The performance will stink if most of the IDs are used up.
You pregenerate all the possible IDs and store them in a table. Whenever you need to get one you can remove one from a random row index and use that as the ID. Database will take care of the concurrency for you so its guarantee unique. if the first three letters are given then you can simply add a where clause to restrict the rows to match that constraint.

How do I find out if a DynamoDB table is empty?

How can I find out if a DynamoDB table contains any items using the .NET SDK?
One option is to do a Scan operation, and check the returned Count. But Scans can be costly for large tables and should be avoided.
The describe table count does not return real time value. The item count is updated every 6 hours.
The best way is to scan only once without any filter expression and check the count. This may not be costly as you are scanning the table only once and it would not scan the entire table as you don't need to scan recursively to find whether the table has any item.
A single scan returns only 1 MB of data.
If the use case requires real time value, this is the best and only option available.
Edit: While the below appears to work fine with small tables on localhost, the docs state
DynamoDB updates this value approximately every six hours. Recent changes might not be reflected in this value.
so only use DescribeTable if you don't need an accurate, up to date figure.
Original:
It looks like the best way to do this is to use the DescribeTable method on AmazonDynamoDBClient:
AmazonDynamoDBClient client = ...
if (client.DescribeTable("FooTable").Table.ItemCount == 0)
// do stuff

SQL Numeric Column forbid Gaps

I'm doing invoice table in my database. I need a integer column to store invoice number. This column has to forbid gap between number. Identity doesn't work because on rollback can produce a gap.
So what I want is:
InvoiceId(Primary key identity) InvoiceNumber(Unique, NOT NUll)
1 1
2 2
10 3
13 4
Is there a special way in sql to do this ?
If there is no solution in sql, how should I do it in c# + entity?
EDIT 1:
additionnal information: A row will be never deleted.
EDIT 2:
Why I need gapLess Column: it's a law requirement (french law). Invoice number as to be gapLess, to show that you didn't removed invoice.
There is no way to protect from gaps if you access your database in parallel.
Simple case:
Process A) creates an invoice. (#1)
Process B) creates an invoice. (#2)
Process A) rolls back it's transaction.
Gap.
You could either lock your whole table for the whole transaction. That means that only one of your processes can create an invoice at the same time. That might be acceptable for small companies where one person creates all invoices by hand.
Or you could leave the column empty and once per night you lock the whole table and write those numbers that are not set yet. That means you get the invoice number later in your invoice process, but it's without gaps.
Or you could read the requirements again. Germany had something equally stupid, but it was only meant to have those numbers on the form for the tax department. So you could use your normal invoice numbers with gaps and when sending them to this bureaucratic monstrosity, you would generate a unique, gap free number on export only.
Because there are multiple users you can't recalculate value at client side. Just create triggers in your database for insert/delete that will recalculate the InvoiceNumber for the entire table.

How to provide Unique ID in Offline mode?

In a client-server accounting application in invoice form when a user saves an invoce it gets An invoice number like 90134 from server and saves the invoice with that number The invoice number is needed for the customer.
So in Offline mode (like when the network dropped) how provide a unique id?
Is it good to use String Id like this pattern: client + incremental number?
I don't want to use GUIDs.
If you know in advance how many invoice numbers you will generate per client during an offline period, would you be able to pre-allocate invoice numbers? e.g. if each client is likely only to generate 4 invoices per offline period, you could allocate a block of 4 numbers to each client. This may involve an extra column in your DB to store a value indicating whether the number is an invoice already created, or a preallocation of a number. Depending on the structure and constraints within your DB, you may also need to store some dummy data to enforce referential integrity.
The downsides would be that your block of numbers may not get used sequentially, or indeed at all, so your invoice numbers would not be in chronological order. Also, you would run into problems if the pool of available numbers is used up.
You can use Guid:
var myUniqueID = Guid.NewID();
In SQL server is corresponding type uniqueidentifier.
In general the Guid is 128-bit number.
More about Guid you can read:
http://en.wikipedia.org/wiki/Globally_unique_identifier
http://msdn.microsoft.com/en-us/library/system.guid.aspx
I suppose the invoice number (integer) is incremental: in this case, since you have no way of knowing the last invoice number, you could save the invoice in a local db/cache/xml without the invoice Number and wait for the network connection to insert the new records in the DB (the invoice number would be generated then)
You could start your numbers for each client at a different range... e.g.:
client 1: 1,000,000
client 2: 2,000,000
client 3: 3,000,000
Update them every now and then when there is a connection to avoid overlaps.
It's not 100% bulletproof, but at least it's better than nothing.
My favorite would still be a GUID for this, since they're always unique.
There is a workaround, but it is merely a "dirty hack", you should seriously reconsider accepting new data entries while offline, especially when dealing with unique IDs to be inserted in many tables.
Say you have an "orders" table and another "orderDetails" table in your local dataset:
1- add a tmpID of type integer in your "orders" table to temporarily identify each unique order.
2- use the tmpID of your newly created order in the rest of the process (say for adding products to the current order in the orderDetails table)
--> once you are connected to the server, in a single transaction do the following
1- insert the first order in the "orders" table
2- get its uniqueID generated on your SQL server
3- search for each line in "orderDetails" that have a tmpID of currentOrder.tmpID and insert them in the "orderDetails" table on your server
4- commit the transaction and continue to the following row.
Keep in mind that this is very bad coding and that it can get real dirty and hard to maintain.
it looks like impossible to create unique numbers with two different systems both offline when it must be chronological and without missing numbers.
imho there is no way if the last number (on the server) was 10, to know if i should return 11 or 12; i would have to know if 11 was already used by another person.
I can only imagine to use a temporary number and later on renumber those numbers, but if the invoices are printed and the number can not be changed, i don't know how you could accomplish such a solution.

Categories

Resources