﻿<?xml version='1.0' encoding='UTF-8'?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>SQLServerCentral / Discuss Content Posted by Asif Sayed / Article Discussions / Article Discussions by Author  / Generating a Sequential Pattern / Latest Posts</title><generator>InstantForum.NET v2.9.0</generator><description>SQLServerCentral</description><link>http://www.sqlservercentral.com/Forums/</link><webMaster>notifications@sqlservercentral.com</webMaster><lastBuildDate>Tue, 18 Jun 2013 21:35:52 GMT</lastBuildDate><ttl>20</ttl><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>We've had a similar situation and deployed a solution like Noels which I think is the best.  It gives you something to lock on to prevent the concurrency problem (which will show up once you get a lot of users and data on the system).  It also will perform must faster because you only have to read one row out of a table that will have only a couple of rows (if one per year) rather than scanning your invoice table for max constantly.</description><pubDate>Thu, 17 May 2007 05:41:00 GMT</pubDate><dc:creator>Samuel Clough</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>hmmm....well it does solve the issue MOMENTARILYhowever if its really deployed over a vast network where a transaction of insert would be like fired so very frequently...the user is definitely gettin more already used errors...i am sure...and plus there are better alternatives already available...nyways this definitely helped thoughh</description><pubDate>Wed, 16 May 2007 22:30:00 GMT</pubDate><dc:creator>mitul surti</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;Iron clad?&lt;/P&gt;&lt;P&gt;&lt;FONT face=Courier&gt;-- prepare test datadeclare @test table (t varchar(50))insert @testselect 'ov1' union allselect 'ov2' union allselect 'ov4' union allselect 'ov31' union allselect 'ssss1' union allselect 'ssss99'-- show data before inserting new valuesselect * from @test-- do the workdeclare @prefix varchar(50)select @prefix = 'ov' -- Throw anything in!insert @testselect	@prefix + convert(varchar, t.n + 1)from	(		select	max(convert(int, substring(t, 1 + len(@prefix), 50))) n		from	@test		where	t like @prefix + '%'			and not substring(t, 1 + len(@prefix), 50) like '%[^0-9]%'	) twhere	not @prefix like '%[0-9]%'	and not t.n like '%[^0-9]%'-- show data after inserting new valuesselect * from @test&lt;/FONT&gt;&lt;/P&gt;</description><pubDate>Sat, 17 Jun 2006 11:57:00 GMT</pubDate><dc:creator>SwePeso</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;I liked your revised approach of letting SQL pick proper index and help speed up performance.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;The goal for this approach was totally eliminate the need to “maintain any sort of counters” and I think I have mentioned that the solution I proposed is for a small to medium size operation, believe it or not it always worked for me since about 8 years &lt;img src='images/emotions/biggrin.gif' height='20' width='20' border='0' title='Big Grin' align='absmiddle'&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt; &lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;I will give it another shot using CLR integration and see how much does it makes difference.&lt;/FONT&gt;&lt;/P&gt;&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt; &lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;Regards,&lt;/FONT&gt;&lt;/P&gt;&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;Asif&lt;/FONT&gt;&lt;/P&gt;</description><pubDate>Thu, 18 May 2006 08:39:00 GMT</pubDate><dc:creator>Asif Sayed</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>How about this string keys are to be avoided (not least because they become foreign keys), also the indexes will be larger and less efficient than integers. This method uses an identity key and a derived column that calculates the invoice id from the identity column. An alternative would be to calculate the invoice id using the function and storing it alongside the identity column, might be worth storing and indexing the year too as likely to group indexes by year, can use check constraints to ensure values are in sync.	create table tbl(id int identity(1,1), dt datetime)	go	create function dbo.GetInvoiceId(@i int, @yr int) returns varchar(10)	as	begin		declare @r varchar(10)		set @r = @i - coalesce((select max(id) from tbl where year(dt) &lt; @yr),0)		return substring(cast(@yr as varchar(4)),3,2) + substring('-000000',1, 7 - len(@r)) + @r	endgobegin	alter table tbl add  MyId as dbo.GetInvoiceId([id], year(dt)) 	insert tbl(dt)	select top 100 '2004-01-01' from sysobjects	insert tbl(dt)	select top 100 '2005-01-01' from sysobjects	insert tbl(dt)	select top 100 '2006-01-01' from sysobjects		select * from tblendgo drop table tblgodrop function dbo.GetId</description><pubDate>Thu, 18 May 2006 02:31:00 GMT</pubDate><dc:creator>Phil.Nicholas</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;I was thinking a bit about the performance problem I mentioned above when creating a sequence.&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;The group by querry could be rewritten so it can correctly use the indexec.&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;The following querry would do the trick:&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt; SET @tmp_invoice_id = (SELECT top 1 (SUBSTRING(invoice_id, 4, 5) + 1)                         FROM Invoice WHERE (invoice_id LIKE @tmp_date + '%')order by  invoive_id desc)&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;This will limit the querry to only retrieve one record and only do one substring and one implicit cast on the data.&lt;/P&gt;</description><pubDate>Thu, 18 May 2006 00:59:00 GMT</pubDate><dc:creator>Heiko Hatzfeld</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>Thankyou all for taking time to put your comments... I am glad to see a healthy discussion here on topic which I started&lt;img src='images/emotions/wink.gif' height='20' width='20' border='0' title='Wink' align='absmiddle'&gt;Regards,Asif</description><pubDate>Wed, 17 May 2006 20:26:00 GMT</pubDate><dc:creator>Asif Sayed</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;Hehe&lt;img src='images/emotions/hehe.gif' height='20' width='20' border='0' title='HeHe' align='absmiddle'&gt;...&lt;img src='images/emotions/biggrin.gif' height='20' width='20' border='0' title='Big Grin' align='absmiddle'&gt;&lt;img src='images/emotions/biggrin.gif' height='20' width='20' border='0' title='Big Grin' align='absmiddle'&gt;&lt;/P&gt;&lt;P&gt;I was refering to the Identity column with primary key constraint &lt;img src='images/emotions/wink.gif' height='20' width='20' border='0' title='Wink' align='absmiddle'&gt;&lt;/P&gt;&lt;P&gt;Should you need this "sequencing" you can use the table and should you could care less about it use the Identity instead.&lt;/P&gt;&lt;P&gt;The sequence is very good to "reserve"  client side batches of candidate keys in one go &lt;img src='images/emotions/wink.gif' height='20' width='20' border='0' title='Wink' align='absmiddle'&gt;&lt;/P&gt;&lt;P&gt;I am certaint that scalability is excellent if you apply all the remomendations I posted &lt;img src='images/emotions/biggrin.gif' height='20' width='20' border='0' title='Big Grin' align='absmiddle'&gt; (I have !) &lt;img src='images/emotions/hehe.gif' height='20' width='20' border='0' title='HeHe' align='absmiddle'&gt;&lt;/P&gt;&lt;P&gt; &lt;/P&gt;</description><pubDate>Wed, 17 May 2006 15:08:00 GMT</pubDate><dc:creator>noeld</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;&lt;STRONG&gt;It should be a separate column and concatenated into the computed column that is displayed to the user.&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;I think thats the most important post in this discussion. I think one of the worst things you can do to a relational DB is to store MORE THEN ONE Information in a field. And if you "force" the field to become a wrong datatype it will even get worse. &lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;Take the Year-Number example... &lt;/P&gt;&lt;P&gt; SET @tmp_invoice_id = (SELECT MAX(SUBSTRING(invoice_id, 4, 5) + 1)                        FROM Invoice WHERE (invoice_id LIKE @tmp_date + '%'))&lt;/P&gt;&lt;P&gt;To find all "Year entries" you can utilize an Index with "like '06%' after that you are using a function to find the maximum value of ALL Invoices for that year. That means in a "worst case" you have to do 99.999 times Substring ?&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;I think the overhead when creating the sequential Invoices can be negelected if you are using a sequence table... Also here is a small suggestion for the self updating of the sequence table. If I am faced with a the same problem, then i usually do it the "lazy way" Update the row i need to update, and if I get a rowcount of "0" then I know that i need to actually insert the row. Updating 0 Rows has no negative performace effect on SQL Server (Assuming correct indexes) and if I first check if the row exists, and then update, then i need to access the index 2 times... Once for checking and once for updating... So I can skip the 2nd Access to the index most of the times. And the Insert will automatically fierd when its needed.&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;But when the reporting season starts this (string) system will hurt you. It is not possible to generate a "good" index on these fields. and when you start running querries this will start to hurt you. It might only start with an concattinated Invoice Number... but in a current  application i am working with this started to run rampart... They needed to change the Datatype from Varchar to Binary to store all the "extra" information (Yes I tried to convice them that this is stupid... trust me I tried.. I am also looking for a Job now where ppl actually listen)&lt;/P&gt;&lt;P&gt;P.s: The suggested solution can still be valid if the number of Invoices remains small. You allways have to think about which compromise you can make... &lt;/P&gt;&lt;P&gt; &lt;/P&gt;</description><pubDate>Wed, 17 May 2006 12:34:00 GMT</pubDate><dc:creator>Heiko Hatzfeld</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;I'm not sure how the function will work with multiple rows, I get a duplicate key error when I try it.&lt;/P&gt;&lt;P&gt;Maybe if it was implemented as a CLR function and flagged as non-deterministic, but I don't think it's worth the trouble.&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 10:54:00 GMT</pubDate><dc:creator>Scott Coleman</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>I love functions...  below is the function declaration but first the insert statmentINSERT INTO dbo.Invoice ( Invoice_id, Customer_name, Invoice_amount )VALUES ( dbo.fn_NextKey(05), 'ACME Corp.', 12345.67 )This technique also works with SELECT inserts for multi-row inserting joy.  The function is also easy to modify for different key compositions mmyy-nnnnnnnnnn or what ever...Cheers!CREATE FUNCTION dbo.fn_NextKey( @year int )RETURNS varchar(10)ASBEGIN   /* ASSERTIONS     * Invoice_Id has a fixed pattern of yy-nnnnnn where yy is last two digits of a year     * and nnnnnn is a 6 digit 0 padded number that is incremented by 1     */    DECLARE @pattern char(3), @answer varchar(10)    SET @pattern = right('00'+convert(varchar(10),@year),2) + '-'       SELECT         @answer = CASE WHEN max(Invoice_id) IS NULL             THEN @pattern + '000001' /* first invoice of given year */            ELSE @pattern + right('000000'+convert(varchar(10),convert(int,substring(max(Invoice_id),4,6))+1),6)             END    FROM dbo.Invoice     WHERE Invoice_id LIKE @pattern+'%'    RETURN @answerEND</description><pubDate>Wed, 17 May 2006 10:29:00 GMT</pubDate><dc:creator>Dennis D. Allen</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;One of my concerns with a sequence table, aside from the additional I/O and other overhead, is that you cannot then easily insert multiple invoices in one statement.  &lt;/P&gt;&lt;P&gt;If, for example, thru some EDI (yes, it is still used) or other process you have a batch of invoices to enter, you must single-step thru them with a sequence table, but not with an identity column.&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;As for a non-numeric, that's true, it could not be in the column itself -- then again, it shouldn't be anyway imo.  It should be a separate column and concatenated into the computed column that is displayed to the user.&lt;/P&gt;&lt;P&gt; &lt;/P&gt;</description><pubDate>Wed, 17 May 2006 10:21:00 GMT</pubDate><dc:creator>ScottPletcher</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;Noel, you're confusing me.  "A sequence table &lt;STRONG&gt;is&lt;/STRONG&gt; the right idea", but "It is not my preferred way"?  So there's another way you prefer that's better than the ones posted, but you're not going to share it with us? &lt;img src='images/emotions/smile.gif' height='20' width='20' border='0' title='Smile' align='absmiddle'&gt;&lt;/P&gt;&lt;P&gt;I agree that the sequence table is a very workable solution and would not worry about scaling if it is done right.  My biggest concern would be guaranteeing that all inserts are done by a stored procedure that correctly accesses the sequence table.&lt;/P&gt;&lt;P&gt;You could argue that the identity field approach should scale better because you only need one action to insert the record, while the sequence table requires an extra action for the update.  This is probably just a theoretical argument, because I can't imagine a real situation where a sequence table approach would break down if all of Noel's suggestions were applied.&lt;/P&gt;&lt;P&gt;On the other hand if you've got such a volume of invoices that you're worried about scaling, you should be able to afford enough hardware to deal with it.  I'd be happy to come help set up your new 32-processor servers for the reasonable sum of twice my current salary. &lt;img src='images/emotions/biggrin.gif' height='20' width='20' border='0' title='Big Grin' align='absmiddle'&gt;&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 10:06:00 GMT</pubDate><dc:creator>Scott Coleman</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>Absolutely</description><pubDate>Wed, 17 May 2006 09:58:00 GMT</pubDate><dc:creator>noeld</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>Will it work in multiuser environment???</description><pubDate>Wed, 17 May 2006 09:51:00 GMT</pubDate><dc:creator>Bhushan</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;First.&lt;/P&gt;&lt;P&gt;The Idea of a Sequence table &lt;STRONG&gt;is&lt;/STRONG&gt; the right idea in this case.&lt;/P&gt;&lt;P&gt;Second. &lt;/P&gt;&lt;P&gt;&lt;EM&gt;"Central location for keys is a concurrency nightmare"&lt;/EM&gt; &lt;STRONG&gt;&lt;FONT color=#dd3333&gt;if&lt;/FONT&gt; &lt;/STRONG&gt;you are not using the appropriate locking mechanisms.&lt;/P&gt;&lt;P&gt;ex: &lt;/P&gt;&lt;UL&gt;&lt;LI&gt;do not compute the sequence year on the query&lt;/LI&gt;&lt;LI&gt;Should you need more than one at a time add a @count param and get only the latest&lt;/LI&gt;&lt;LI&gt;if you have multiple sequences make sure you have a primary key on the sequencing key&lt;/LI&gt;&lt;LI&gt;should the table grow make sure that the update is using (with rowlock)&lt;/LI&gt;&lt;LI&gt;Last but not least if the number of proccess competing for keys is very ( and I mean very &lt;img src='images/emotions/wink.gif' height='20' width='20' border='0' title='Wink' align='absmiddle'&gt; ) high use sp_tableoption and "pin" the sequence table.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;As you can see I have experience with this structure and have been successfuly able to implemet such construct.&lt;/P&gt;&lt;P&gt;It is not my preffered way but it is very portable and very flexible &lt;img src='images/emotions/wink.gif' height='20' width='20' border='0' title='Wink' align='absmiddle'&gt;&lt;/P&gt;&lt;P&gt;Cheers,&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt; &lt;/P&gt;</description><pubDate>Wed, 17 May 2006 09:42:00 GMT</pubDate><dc:creator>noeld</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;Mark,Where are you updating the stored value? I have used this a few times and have not seen any impact on scalability but it may not have been under a big enough load. The statement as I posted it gets in and out of the table very quickly so I am not sure what kind of concurrency problems you might be referring to. Please give us a little more detail before I use this again!&lt;/P&gt;&lt;P&gt;Scott,I like your idea as well. It wouldn't be hard to create a job that ran at the beginning of every year to reset the seed and increment of the identity column. The only downside (very minor imo) would be that you can't put any non-numeric characters in the field itself.&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 09:23:00 GMT</pubDate><dc:creator>Tatsu</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;&amp;gt;&amp;gt; "SET IDENTITY_INSERT ON" would be needed for prior year, with logic similar to above, but hopefully that would be relatively rare. &amp;lt;&amp;lt;&lt;/P&gt;&lt;P&gt;In fact, in most systems, especially dealing with invoices, it should never be allowed -- once the current year is past, &lt;STRONG&gt;no&lt;/STRONG&gt; &lt;STRONG&gt;new&lt;/STRONG&gt; invoices with the prior yr on them should be created.&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 08:59:00 GMT</pubDate><dc:creator>ScottPletcher</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>Or better yetupdate SequenceTableset @NewSequenceNumber = CurrentSequenceNumber = CurrentSequenceNumber + 1 where SequenceYear = year(getdate())Having said that, central locations for keys are a concurrency nightmare for anything that needs to scale. I would generally steer clear.</description><pubDate>Wed, 17 May 2006 08:55:00 GMT</pubDate><dc:creator>Mark Hickin</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;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]):&lt;/P&gt;&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;P&gt;&lt;FONT face="Courier New"&gt;update SequenceTableset @NewSequenceNumber = CurrentSequenceNumber + 1, CurrentSequenceNumber = @NewSequenceNumberwhere SequenceYear = year(getdate())&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;The update statement could also be executed from a user-defined function that concatenates the year and sequence number into a string.&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 08:45:00 GMT</pubDate><dc:creator>Tatsu</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 08:45:00 GMT</pubDate><dc:creator>Scott Coleman</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;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.&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 08:21:00 GMT</pubDate><dc:creator>ScottPletcher</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;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.&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;&lt;P&gt;SET&lt;/FONT&gt;&lt;FONT size=2&gt; @tmp_date &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;RIGHT(&lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;CAST&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;YEAR&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;GETDATE&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;())&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;+&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;CASE&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;WHEN&lt;/FONT&gt;&lt;FONT size=2&gt; @year_flag &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'P'&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;THEN&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;-&lt;/FONT&gt;&lt;FONT size=2&gt;1 &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;ELSE&lt;/FONT&gt;&lt;FONT size=2&gt; 0 &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;END&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;AS&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;CHAR&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;4&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)),&lt;/FONT&gt;&lt;FONT size=2&gt;2&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;+&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'-'&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;while&lt;/FONT&gt;&lt;FONT size=2&gt; 1&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;1 &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;begin&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    SET&lt;/FONT&gt;&lt;FONT size=2&gt; @new_invoice_id &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; @tmp_date&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&lt;FONT color=#0000ff&gt;        &lt;/FONT&gt;+&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;RIGHT(&lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;STR&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;ISNULL&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;&lt;FONT color=#0000ff&gt;            &lt;/FONT&gt;CAST&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(RIGHT(&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&lt;FONT color=#0000ff&gt;                &lt;/FONT&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;SELECT&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;MAX&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;invoice_id&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;FROM&lt;/FONT&gt;&lt;FONT size=2&gt; dbo&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;FONT size=2&gt;Invoice &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;WHERE&lt;/FONT&gt;&lt;FONT size=2&gt; invoice_id &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;LIKE&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;@tmp_date &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;+&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'%'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;))&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&lt;FONT color=#0000ff&gt;            &lt;/FONT&gt;,&lt;/FONT&gt;&lt;FONT size=2&gt;5&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;AS&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;+&lt;/FONT&gt;&lt;FONT size=2&gt; 100001&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&lt;FONT color=#0000ff&gt;        &lt;/FONT&gt;,&lt;/FONT&gt;&lt;FONT size=2&gt;100001&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;),&lt;/FONT&gt;&lt;FONT size=2&gt;6&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;/FONT&gt;&lt;FONT size=2&gt;0&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;),&lt;/FONT&gt;&lt;FONT size=2&gt;5&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;/* For testing purposes, uncomment the following code to randomly insert conflicting records&lt;FONT color=#0000ff&gt;    &lt;/FONT&gt;if rand() &amp;gt; 0.6&lt;FONT color=#0000ff&gt;        &lt;/FONT&gt;insert into Invoice (invoice_id, customer_name, invoice_amount) values(@new_invoice_id, @customer_name, @invoice_amount)*/&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    insert&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;into&lt;/FONT&gt;&lt;FONT size=2&gt; Invoice &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;invoice_id&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;/FONT&gt;&lt;FONT size=2&gt; customer_name&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;/FONT&gt;&lt;FONT size=2&gt; invoice_amount&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    select&lt;/FONT&gt;&lt;FONT size=2&gt; @new_invoice_id&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;/FONT&gt;&lt;FONT size=2&gt; @customer_name&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;/FONT&gt;&lt;FONT size=2&gt; @invoice_amount&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    where&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;not&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;exists(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; Invoice &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;holdlock&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;where&lt;/FONT&gt;&lt;FONT size=2&gt; invoice_id &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; @new_invoice_id&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    if&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;@@ROWCOUNT&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;FONT size=2&gt; 0 &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;breakEND&lt;/P&gt;&lt;/FONT&gt;</description><pubDate>Wed, 17 May 2006 08:18:00 GMT</pubDate><dc:creator>Scott Coleman</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;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)?&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 07:04:00 GMT</pubDate><dc:creator>Onskee</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;For SQLServer Magazine subscribers, here is a somewhat related artitcle &lt;/P&gt;&lt;P&gt;&lt;A href="http://www.sqlmag.com/Article/ArticleID/48165/sql_server_48165.html"&gt;http://www.sqlmag.com/Article/ArticleID/48165/sql_server_48165.html&lt;/A&gt;&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 07:00:00 GMT</pubDate><dc:creator>Greg Burns</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;Asif,&lt;/P&gt;&lt;P&gt;If it is your first article then I must say -decently written article. &lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;Anyways, it was a good article and keep sharing.&lt;img src='images/emotions/smile.gif' height='20' width='20' border='0' title='Smile' align='absmiddle'&gt;&lt;/P&gt;&lt;P&gt;[Aarez]&lt;/P&gt;&lt;P&gt; &lt;/P&gt;</description><pubDate>Wed, 17 May 2006 06:52:00 GMT</pubDate><dc:creator>Aarez</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;Just makes sure to commit the transaction at the end of the stored procedure (or rollback in case of an error).&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 06:52:00 GMT</pubDate><dc:creator>ben salemi</dc:creator></item><item><title>RE: Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>&lt;P&gt;Asif,&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;Mark&lt;/P&gt;</description><pubDate>Wed, 17 May 2006 06:02:00 GMT</pubDate><dc:creator>SuperDBA-207096</dc:creator></item><item><title>Generating a Sequential Pattern</title><link>http://www.sqlservercentral.com/Forums/Topic275399-295-1.aspx</link><description>Comments posted to this topic are about the content posted at &lt;A HREF="http://www.sqlservercentral.com/columnists/aSayed/generatingasequentialpattern.asp"&gt;http://www.sqlservercentral.com/columnists/aSayed/generatingasequentialpattern.asp&lt;/A&gt;</description><pubDate>Tue, 25 Apr 2006 21:27:00 GMT</pubDate><dc:creator>Asif Sayed</dc:creator></item></channel></rss>