Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Next Sequence Number from table

Author  Topic 

kpgraci
Yak Posting Veteran

68 Posts

Posted - 2012-03-06 : 10:40:15
I have a table with the next receipt number to be used for printing a cash receipt.

nextNo int

I want to query the table to return this number, then increment the number, and do it is sich a way that no other process can come in between the query and increment so as to preserve the integrity of the contiguous receipt number sequence.

The application is an asp.net website with potentially multiple simultaneous request for the next receipt number.

If I craft a single query (which I'm no 100% sure how to do) will this meet my requirements of 'locking out' other users until it is complete?

for example something like this:

SELECT nextNo FROM Table; Update Table SET nextNo=nextNo+1;

guidance welcome :)

kpg

kpg

X002548
Not Just a Number

15586 Posts

Posted - 2012-03-06 : 11:19:06
Are you using stored procedures?

Why don't you just use an identity column?



Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/


Go to Top of Page

X002548
Not Just a Number

15586 Posts

Posted - 2012-03-06 : 11:27:35
whats the DDL of that table..I use a column called InUSe char(1)

I was gonna suggest this...but id doesn't seem to be holding a lock

CREATE TABLE myTable99(NextID int, InUse char(1))
GO

INSERT INTO myTable99(NextID, InUse)
SELECT 1, 'N'

SELECT * FROM myTable99

UPDATE myTable99 WITH (TABLOCK, HOLDLOCK) SET Inuse = 'Y'




Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/


Go to Top of Page

kpgraci
Yak Posting Veteran

68 Posts

Posted - 2012-03-06 : 11:29:41
No, Im not using SP but I can.

I'm not using an identity clumn becuase I have multiple diffeent users each with their own unique nextno

the actual talbe is as follows:

custID int (FK)
nextNo int

thx

kpg
Go to Top of Page

X002548
Not Just a Number

15586 Posts

Posted - 2012-03-06 : 11:32:08
you are going to need to figure out how to hold a row lock until AFTER your row is inserted

Do you have a unique constraint on that column in the destination table?



Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/


Go to Top of Page

kpgraci
Yak Posting Veteran

68 Posts

Posted - 2012-03-06 : 11:47:34
quote:
Originally posted by X002548

you are going to need to figure out how to hold a row lock until AFTER your row is inserted

Do you have a unique constraint on that column in the destination table?


No. Different users can have the same nextNo, however unlikly.

kpg
Go to Top of Page

X002548
Not Just a Number

15586 Posts

Posted - 2012-03-06 : 12:15:35
so what's the primary key of your data table?

ClientID, NextNo?

I sure wonder why you would care about a cash receipt number being sequential..sounds like a bad idea...amount being posted for the wrong client..reports forget the client id...

Still..it all comes down to locking the rows...

And you don't find that this could be a bottle neck?






Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/


Go to Top of Page

kpgraci
Yak Posting Veteran

68 Posts

Posted - 2012-03-06 : 12:52:55
quote:
Originally posted by X002548

so what's the primary key of your data table?

ClientID, NextNo?

I sure wonder why you would care about a cash receipt number being sequential..sounds like a bad idea...amount being posted for the wrong client..reports forget the client id...

Still..it all comes down to locking the rows...

And you don't find that this could be a bottle neck?



The table has no PK.

My customers want the numbers to be sequential.

Bottle neck? Maybe, not sure about the performace implications.

I came up with something that seems to work, but I'm not usre how foolproof it is... here's my code. I'm using transactions and the key line is:

UPDATE NextNumber SET @Next = LastReceiptNo = LastReceiptNo + 1 WHERE SN=@SN


Using myConnection As New SqlConnection(LoginClass.getConnectionString)

myConnection.Open()

Dim transaction As SqlTransaction = myConnection.BeginTransaction

Dim myCommand As SqlCommand = myConnection.CreateCommand

myCommand.Transaction = transaction

'Transaction 1 //////////////////////////////////////////////////////////

sql = "UPDATE NextNumber SET @Next = LastReceiptNo = LastReceiptNo + 1 WHERE SN=@SN"

myCommand.CommandText = sql

Dim NextNoParam As SqlParameter = myCommand.Parameters.AddWithValue("Next", 0)

NextNoParam.Direction = ParameterDirection.Output

myCommand.Parameters.AddWithValue("SN", sn)

n = myCommand.ExecuteNonQuery() 'returns number of rows affected

If n = 1 Then

'Transaction 2 //////////////////////////////////////////////////////////

'cleanup
myCommand.Parameters.Clear()

sql = "INSERT INTO Receipts ReceiptNo VALUES @ReceiptNo WHERE SN=@SN SET @ID = SCOPE_IDENTITY()"

Dim IDParam As SqlParameter = myCommand.Parameters.AddWithValue("ID", -1)
myCommand.Parameters.AddWithValue("SN", sn)
myCommand.Parameters.AddWithValue("ReceiptNo", NextNoParam.Value)

myCommand.CommandText = sql

n = myCommand.ExecuteNonQuery() 'returns number of rows affected

If n = 1 Then
ret = IDParam.Value & "|" & NextNoParam.Value
transaction.Commit()
Else
transaction.Rollback()
End If

'end of Transaction 2 //////////////////////////////////////////////////////////

Else
transaction.Rollback()
End If

End Using






kpg
Go to Top of Page

kpgraci
Yak Posting Veteran

68 Posts

Posted - 2012-03-06 : 13:27:04
I take that back, the PK is going to be ClientID in my example.

That was an example, in reality it is SN, a 6 character alphanumeric, but it will be unique in this table, so I will make it the PK.

I think

UPDATE NextNumber SET @Next = LastReceiptNo = LastReceiptNo + 1 WHERE SN=@SN

should work for me, no other process will interrupt a sinlge query, I'm thinking.



kpg
Go to Top of Page

LoztInSpace
Aged Yak Warrior

940 Posts

Posted - 2012-03-06 : 22:57:55
Brett is right - this is a crap thing to be attempting.
You will kill concurrency using this method because you can't pick the next ID until the transaction currently being processed has finished. If your customer wants to live with that constraint then so be it but it won't scale at all.
Your next+1 method won't work either if you turn on snapshot isolation (which you should if you want decent performance).

Why on earth do you want numbers without gaps? It's a crazy thing to want and generally has no geniune business merit. What would they be doing in a "real" situation? Have only one till? Have one little old lady handing out receipt numbers as customers leave the store? What happens when she spills coffee on the reciept book?
Just use an identity and live with the gaps.
Go to Top of Page
   

- Advertisement -