| Author |
Topic |
|
brianphilpot
Starting Member
3 Posts |
Posted - 2005-11-08 : 09:02:25
|
| Hello,I have been tasked with creating a new table with a unique Identity key. Instead of the the standard integer automatically incrementing by one on each insert, my client wants the primary key to have five digits AA000 through ZZ999.So, the first insert into the table would have a unique primary key of AA000, the next would be AA001... then when it gets to AA999 it would then flip to AB000.I have no idea where to even start. If anyone can point me in the right direction, with some possible code samples or something I would be very appreciative.Thanks,Brian |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2005-11-08 : 09:27:28
|
| Doing a primary key like this does not sound like a good idea. It really doesn't have any advantages, and has a lot of disadvantages: increased storage, slower operations, and harder to manage.Most likely, they will have plent of time to regret this.CODO ERGO SUM |
 |
|
|
X002548
Not Just a Number
15586 Posts |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2005-11-08 : 10:07:09
|
I totaly agree with MVJ. We had a legacy app that started out with char(4) hex codes. As they ran out of values they increased the values to base36 then eventually used special characters so customerCodes ended up like '[^{0'. You can imagine our help line conversations, HelpDesk: "May I have your customer code please?" Customer: "Yes, it's left square bracket, carrot, left squiggly, Zero (or Oh)...I can't tell"To support that system as we transitioned to new technology I wrote a function to translate integers to and from these codes and left the legacyCode in our new tables like this:set nocount onuse northwindif object_id('dbo.fnCustomCode') > 0 drop function dbo.fnCustomCodegocreate function dbo.fnCustomCode(@i int)returns char(5)asbegin --translates in between 0 and 675999 --to AA000 to ZZ999. --check for valid range if @i < 0 or @i > 675999 begin return cast('RANGE' as char(5)) end declare @pk char(5) ,@letter char(26) set @letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' set @pk = substring(@letter, ((@i/1000)/26)+1, 1) + substring(@letter, ((@i/1000)%26)+1, 1) + right('000' + convert(varchar,@i % 1000),3) return @pkendgocreate table Junk (junkid int identity(0,1) primary key not null ,CustomCode as dbo.fnCustomCode(junkid))goset identity_insert junk oninsert junk (junkid)select -1 unionselect 0 union select 1 unionselect 999 union select 1000 unionselect 2000 unionselect 26999 unionselect 27000 unionselect 675999 unionselect 676000set identity_insert junk offselect * from junkgodrop table junkdrop function dbo.fnCustomCodeBe One with the OptimizerTG |
 |
|
|
brianphilpot
Starting Member
3 Posts |
Posted - 2005-11-08 : 10:20:35
|
| Wow.. so many great responses.Thanks all.As I read your responses and thought about this some more, I realized my client wasn't really asking for me to create this primary key. They just want the system to automatically generate a new part number for there products (which doesn't at all mean it needs to be the primary key.)So, I have decided to just use a standard identity column (incrementing integer by 1) for the primary key in the Parts table. But then I prepopulated a new table (Placeholders) with all of the possible Part Numbers in it, from AA000 to ZZ999 along with a column for the corresponding PartID. And when I create a new record in the Parts table, I just look into the Placeholders table for the lowest number Placeholder without a PartID assigned and assign it.I am sorry for asking everyone for something that I really didn't need, but I really wouldn't have been able to figure this out without all of your help. Thanks everyone so much!Brian |
 |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2005-11-08 : 10:31:16
|
| The problem with using a seperate process to "assign" codes is the same problem you'll have with a custom identity column. You'll need to deal with concurrency issues (collisions, blocking, and maybe deadlocking)The additional prepopulated table is a good idea, just include an integer partid column with it. Then you join on the parts table on partid to show the code. That way you won't need to look up the max unassigned value and then assign it.This is a good alternative to the function (above) that translates integers to your custom codes.Be One with the OptimizerTG |
 |
|
|
blindman
Master Smack Fu Yak Hacker
2365 Posts |
Posted - 2005-11-08 : 10:46:31
|
Go ahead and use a standard incrementing identiy as your primary key, and then let modulo arithmetic come to your rescue:declare @PartID intset @PartID = 675999select char(ascii('A')+(@PartID / 26000)) + char(ascii('A')+(@PartID / 1000) % 26) + right('000' + cast((@PartID % 1000) as varchar(3)), 3)What you will do after 675,999 parts is up to your client. |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2005-11-08 : 11:00:31
|
quote: Originally posted by blindman Go ahead and use a standard incrementing identiy as your primary key, and then let modulo arithmetic come to your rescue:declare @PartID intset @PartID = 675999select char(ascii('A')+(@PartID / 26000)) + char(ascii('A')+(@PartID / 1000) % 26) + right('000' + cast((@PartID % 1000) as varchar(3)), 3)What you will do after 675,999 parts is up to your client.
Yes! Very nice, that is exactly what I recommend as well. And thanks for saving me the time to try to figure out the formula ! |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2005-11-08 : 11:11:51
|
You could implement it as a computed column, and add an index if you want to do lookups on the computed column.create table MyTable(PK int not nullidentity(1,1) primary key clustered,PART_DESC varchar(20) not null,PART_CODE as convert(char(5), char(ascii('A')+(PK / 26000)) + char(ascii('A')+(PK / 1000) % 26) + right('000' + cast((PK % 1000) as varchar(3)), 3)))insert into MyTable (PART_DESC) select 'My Part Desc'select * from MyTabledrop table MyTable(1 row(s) affected)PK PART_DESC PART_CODE ----------- -------------------- --------- 1 My Part Desc AA001(1 row(s) affected)CODO ERGO SUM |
 |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2005-11-08 : 11:33:38
|
looks pretty close to the solution in my original post Be One with the OptimizerTG |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2005-11-08 : 11:46:16
|
| TG -- Yes, that is true. Both are great (and very similiar). |
 |
|
|
|