Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 
        
Home       Members    Calendar    Who's On


Add to briefcase 123»»»

Generating a Sequential Pattern Expand / Collapse
Author
Message
Posted Tuesday, April 25, 2006 9:27 PM
Grasshopper

GrasshopperGrasshopperGrasshopperGrasshopperGrasshopperGrasshopperGrasshopperGrasshopper

Group: General Forum Members
Last Login: Thursday, February 14, 2008 2:21 PM
Points: 18, Visits: 3
Comments posted to this topic are about the content posted at http://www.sqlservercentral.com/columnists/aSayed/generatingasequentialpattern.asp
Post #275399
Posted Wednesday, May 17, 2006 6:02 AM


UDP Broadcaster

UDP BroadcasterUDP BroadcasterUDP BroadcasterUDP BroadcasterUDP BroadcasterUDP BroadcasterUDP BroadcasterUDP Broadcaster

Group: General Forum Members
Last Login: Wednesday, January 2, 2013 12:15 PM
Points: 1,443, Visits: 711

Asif,

Nice article!  I've dealt with this problem before (I implemented a client-side solution instead of an SQL based solution).  I like the approach and probably will use it in the future.

Mark

Post #280650
Posted Wednesday, May 17, 2006 6:52 AM
Forum Newbie

Forum NewbieForum NewbieForum NewbieForum NewbieForum NewbieForum NewbieForum NewbieForum Newbie

Group: General Forum Members
Last Login: Thursday, March 22, 2012 12:48 PM
Points: 4, Visits: 11

If you did want to worry about concurrency, there is always the technique of serializing the requests by obtaining a row lock on a common resource.

Imagine a new table (SERIALIZER) that has one row, start a transaction and update the row as the first action in the stored procedure.  Now, other calls to the stored proc will wait on the first call to finish the transaction.

Just makes sure to commit the transaction at the end of the stored procedure (or rollback in case of an error).

Post #280670
Posted Wednesday, May 17, 2006 6:52 AM
Grasshopper

GrasshopperGrasshopperGrasshopperGrasshopperGrasshopperGrasshopperGrasshopperGrasshopper

Group: General Forum Members
Last Login: Saturday, February 15, 2014 10:38 AM
Points: 11, Visits: 18

Asif,

If it is your first article then I must say -decently written article.

I have also dealt with such situations many times but what I noticed in your solution was that you did not handle the case if maximum possible Invoice Id (i.e. yy-99999) was already generated. However, you put enough attention not to let generate a duplicate.

Anyways, it was a good article and keep sharing.

[Aarez]

 

Post #280671
Posted Wednesday, May 17, 2006 7:00 AM


SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Friday, June 21, 2013 4:41 PM
Points: 29, Visits: 52

For SQLServer Magazine subscribers, here is a somewhat related artitcle

http://www.sqlmag.com/Article/ArticleID/48165/sql_server_48165.html

Post #280675
Posted Wednesday, May 17, 2006 7:04 AM
Valued Member

Valued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued Member

Group: General Forum Members
Last Login: Thursday, July 10, 2014 10:08 AM
Points: 59, Visits: 194

Is there a benefit to dealing with storing and looking up the string 'yy-xxxxx', rather than 2 numerical fields (a year field and some incrementing number)?




Post #280677
Posted Wednesday, May 17, 2006 8:18 AM
SSCrazy

SSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazy

Group: General Forum Members
Last Login: Friday, July 18, 2014 12:13 PM
Points: 2,837, Visits: 1,138

I think this code solves the problem of concurrent inserts.  One SELECT is used to generate the new invoice id, but if another user manages to sneak it in first the code loops and tries the next number.

SET @tmp_date = RIGHT(CAST(YEAR(GETDATE()) + CASE WHEN @year_flag = 'P' THEN -1 ELSE 0 END AS CHAR(4)),2) + '-'

while 1=1 begin
    SET @new_invoice_id = @tmp_date
        + RIGHT(STR(ISNULL(
            CAST(RIGHT(
                (SELECT MAX(invoice_id) FROM dbo.Invoice WHERE invoice_id LIKE (@tmp_date + '%'))
            ,5) AS int) + 100001
        ,100001),6,0),5)

/* For testing purposes, uncomment the following code to randomly insert conflicting records
    if rand() > 0.6
        insert into Invoice (invoice_id, customer_name, invoice_amount) values(@new_invoice_id, @customer_name, @invoice_amount)
*/

    insert into Invoice (invoice_id, customer_name, invoice_amount) 
    select @new_invoice_id, @customer_name, @invoice_amount
    where not exists(select null from Invoice with(holdlock) where invoice_id = @new_invoice_id)

    if
@@ROWCOUNT > 0 break
END




Post #280703
Posted Wednesday, May 17, 2006 8:21 AM
SSCommitted

SSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommitted

Group: General Forum Members
Last Login: Today @ 5:31 PM
Points: 1,977, Visits: 2,926

Yes.  Or possibly even a single identity column that was re-seeded each year to yy00000[0]; the "-" could be added prior to display just for the "visual effect" for the user.  "SET IDENTITY_INSERT ON" would be needed for prior year, with logic similar to above, but hopefully that would be relatively rare.



SQL DBA,SQL Server MVP('07, '08, '09)
"In America, every man is innocent until proven broke!" Brant Parker
Post #280706
Posted Wednesday, May 17, 2006 8:45 AM
SSCrazy

SSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazy

Group: General Forum Members
Last Login: Friday, July 18, 2014 12:13 PM
Points: 2,837, Visits: 1,138

Yes, this is a much easier problem if you just use an integer identity field.  You could create a view using "STUFF(CAST(invoice_id as char(8)),3,0,'-') as invoice_id" for anything that insists on seeing it that way.

I have tried for years to convince boneheads that if they want to see numbers with leading zeros, embedded dashes, etc, in their stupid spreadsheets then they should figure out how to format a column in Excel rather than try to dictate that I need to change all the numeric fields in the database to characters.  If you have better luck than I do, let me know how you do it.  Funny how after they run the data through Excel and lose all the leading zeroes they still want to blame the database.

The last time someone whined about storing the leading zeroes I offered to print a binary dump of the data pages to prove that every 32-bit integer field did indeed have all of the leading zero bits intact.  I haven't had any complaints since then, but it's only a matter of time.




Post #280721
Posted Wednesday, May 17, 2006 8:45 AM


SSC Veteran

SSC VeteranSSC VeteranSSC VeteranSSC VeteranSSC VeteranSSC VeteranSSC VeteranSSC Veteran

Group: General Forum Members
Last Login: Monday, July 7, 2014 12:50 PM
Points: 292, Visits: 264

Why not just store the sequence number in a table and perform an update statement like this (assumes a table called SequenceTable exists and has two columns, CurrentSequenceNumber [int or bigint] and SequenceYear [int]):

update SequenceTable
set @NewSequenceNumber = CurrentSequenceNumber + 1, CurrentSequenceNumber = @NewSequenceNumber
where SequenceYear = year(getdate())

This gives you the next number in the sequence and updates the sequence table in a single transaction. When the new year rolls around just add a new row to the sequence table for the new year and start the sequence at zero again.

The update statement could also be executed from a user-defined function that concatenates the year and sequence number into a string.



Bryant E. Byrd, BSSE MCDBA MCAD
Business Intelligence Administrator
MSBI Administration Blog
Post #280722
« Prev Topic | Next Topic »

Add to briefcase 123»»»

Permissions Expand / Collapse