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.
| Author |
Topic |
|
benking9987
Posting Yak Master
124 Posts |
Posted - 2009-04-09 : 20:14:59
|
| I'm trying to have my SQL database create UPC codes on the fly based on the inputs from my table and. I understand I'll need to create a function that generates the first 11 digits of my UPC code, then another function that will generate the Check Digit for the UPC code. If you're not familiar with how UPC codes work, read on I will show what I know here.What I have so far is a function that will generate the first 11 numbers I need and a trigger that takes the results of that function and puts it into my table for me.Function:CREATE function UPC_Start (@id int)returns char(11)asbeginreturn '87022' + right('000000' + convert(varchar(11), @id),6)endTrigger:CREATE trigger UPC_Start_Insert on Child_Tableafter insert asupdate Child_Tableset Child_Table.UPC_Start=UPC_Start(Child_Table.ChildID)from Child_Tableinner join inserted on Child_Table.ChildID= inserted.ChildIDThis much works perfectly. What I need is the 12th digit called the "Check Digit" of the UPC. Its calculated by taking the digits in the odd numbered locations, adding them up and multiplying them by 3. Then taking the digits in the even numbered locations and adding them to that number. You then take that sum and whatever number you must add to that number to get the next even multiple of 10 is your check digit. For example:UPC: 870211111303Odd placed numbers: 8 + 0 + 1 + 1 + 1 + 0 = 11 * 3 = 33Even placed numbers: 7 + 2 + 1 + 1 + 3 = 14Sum of Both: 47Next even multiple of 10 is 50: 50-47 = 3The next part of the function in SQL I need is something to calculate this Check Digit. I found a post on another forum that gave me this syntax, but I'm new enough to SQL that I can't understand how to adapt it to what I already have.CREATE PROCEDURE genCheckDigit(@strUPC varchar(11), @checkDigit int output) ASdeclare @intTmp1 intdeclare @intTmp2 intset @checkDigit = -1if isnumeric(@strUPC) = 0BEGIN RAISERROR ('UPC is not numeric',16,1)ENDselect @strUPC = rtrim(ltrim(@strUPC))While len(@strUPC) < 11 set @strUPC = '0' + @strUPCSelect @intTmp1 = 0 + Substring(@strUPC,1,1) + Substring(@strUPC,3,1) + Substring(@strUPC,5,1) + Substring(@strUPC,7,1) + Substring(@strUPC,9,1) + Substring(@strUPC,11,1)select @intTmp1 = @intTmp1 * 3Select @intTmp2 = 0 + Substring(@strUPC,2,1) + Substring(@strUPC,4,1) + Substring(@strUPC,6,1) + Substring(@strUPC,8,1) + Substring(@strUPC,10,1)select @intTmp1 = @intTmp2 + @intTmp1select @intTmp1 = (10 - (@intTmp1 % 10)) % 10select @checkDigit = @intTmp1 |
|
|
yosiasz
Master Smack Fu Yak Hacker
1635 Posts |
Posted - 2009-04-10 : 15:08:06
|
| show us some sample value for which you want to create UPC code...like a row of 10 items. This looks like a fun task<><><><><><><><><><><><><><><><><><><><><><><><><>If you don't have the passion to help people, you have no passion |
 |
|
|
benking9987
Posting Yak Master
124 Posts |
Posted - 2009-04-10 : 17:50:58
|
| Thanks for the reply. We'll determine if it was fun later! For now, thanks for being willing to help out.The field for ChildID is the PK of the ChildTable, so the data is sequentially created and inserted on every new item. You can tell that the field for UPC_Start is the 11 digit code that is coming from the function and trigger indicated above. You can see that it essentially adds "87022" to every childID, plus pads the remaining 6 number with a zero in the case that the ChildID is less than 6 digits long. I'd like to create a similar function to generate the UPC_CheckDigit. as stated above, that digit is a mathmatical derivation based on what's included in UPC_Start. The column for UPC then simply becomes a string made up of UPC_Start + UPC_CheckDigitMy first idea was to create these data components separately as I've done here, but then I thought perhaps there was a way to do ALL three steps in one function, then create a trigger to insert the derived value on every new entry.ChildID| UPC_Start| UPC_CheckDigit| UPC|37175| 87022037175| Null| Null|37176| 87022037176| Null| Null|37177| 87022037177| Null| Null|37178| 87022037178| Null| Null|37179| 87022037179| Null| Null|37180| 87022037180| Null| Null|37181| 87022037181| Null| Null|37182| 87022037182| Null| Null|37183| 87022037183| Null| Null|37184| 87022037184| Null| Null|37185| 87022037185| Null| Null|37186| 87022037186| Null| Null|37187| 87022037187| Null| Null|Thanks again for your help. I look forward to your reply. |
 |
|
|
yosiasz
Master Smack Fu Yak Hacker
1635 Posts |
Posted - 2009-04-10 : 18:19:26
|
| yes you can do it in one step but you first have to massage your existing data. as it stands now, you haev one field for UPC_Start and another one for UPC_CheckDigit. DO you want those fieds merged eventually or you want them to stay as is two seperate fields. Another question for youif isnumeric(@strUPC) = 0BEGINRAISERROR ('UPC is not numeric',16,1)ENDwill whatever you will be converting into UPC always be numeric, alpha or both or it can be any of the above?And do you want your final UPC to be numeric, alpha, or combination? Can you clarify these please.<><><><><><><><><><><><><><><><><><><><><><><><><>If you don't have the passion to help people, you have no passion |
 |
|
|
yosiasz
Master Smack Fu Yak Hacker
1635 Posts |
Posted - 2009-04-10 : 18:28:52
|
| in one function SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE function [dbo].[UPC_IT] (@id int)returns char(50)asBEGIN DECLARE @UpCStart AS CHAR(11) SET @UpCStart = '87022' + right('000000' + convert(varchar(11), @id),6) declare @intTmp1 int declare @intTmp2 int DECLARE @checkDigit int set @checkDigit = -1 select @UpCStart = rtrim(ltrim(@UpCStart)) begin While len(@UpCStart) < 11 set @UpCStart = '0' + @UpCStart Select @intTmp1 = 0 + Substring(@UpCStart,1,1) + Substring(@UpCStart,3,1) + Substring(@UpCStart,5,1) + Substring(@UpCStart,7,1) + Substring(@UpCStart,9,1) + Substring(@UpCStart,11,1) select @intTmp1 = @intTmp1 * 3 Select @intTmp2 = 0 + Substring(@UpCStart,2,1) + Substring(@UpCStart,4,1) + Substring(@UpCStart,6,1) + Substring(@UpCStart,8,1) + Substring(@UpCStart,10,1) select @intTmp1 = @intTmp2 + @intTmp1 select @intTmp1 = (10 - (@intTmp1 % 10)) % 10 select @checkDigit = @intTmp1 END BEGIN return CAST(@UpCStart AS VARCHAR(20)) + CAST(@checkDigit AS VARCHAR(20)) endENDCREATE TABLE UPCMango( ChildID INT, UPC_Start CHAR(11), UPC_CheckDigit INT, FinalUPC INT)INSERT INTO UPCMango (ChildID) SELECT '37175'UNION ALLSELECT '37176'UNION ALLSELECT '37177'UNION ALLSELECT '37178'UNION ALLSELECT '37179'UNION ALLSELECT '37180'UNION ALLSELECT '37181'UNION ALLSELECT '37182'UNION ALLSELECT '37183'UNION ALLSELECT '37184'UNION ALLSELECT '37185'UNION ALLSELECT '37186'UNION ALLSELECT '37187'SELECT dbo.UPC_IT(ChildID) FROM UPCMangocan you confirm the accuracy of the UPC..I am sure there is a better way of doing it than this<><><><><><><><><><><><><><><><><><><><><><><><><>If you don't have the passion to help people, you have no passion |
 |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2009-04-10 : 20:00:56
|
| It's probably better to have your printing program generate the barcode and check digit. There's a project here that can help:http://www.codeproject.com/KB/graphics/upc_a_barcode.aspxIf you need to generate the check digit in SQL Server, you can probably modify that code into a CLR stored procedure and register it in your database. |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
|
|
benking9987
Posting Yak Master
124 Posts |
Posted - 2009-04-13 : 15:17:25
|
| Thank you yosiasz!!! I wasn't able to look at this solution until now, but I think you've gotten it figured out.I checked the CheckDigit and its working properly. See below.test 37538 870220375383test1 37539 870220375390test2 37540 870220375406 |
 |
|
|
yosiasz
Master Smack Fu Yak Hacker
1635 Posts |
Posted - 2009-04-13 : 17:14:09
|
| I would go with Peso's and other's. why recreate the wheel? The above two have it wrapped neatly<><><><><><><><><><><><><><><><><><><><><><><><><>If you don't have the passion to help people, you have no passion |
 |
|
|
benking9987
Posting Yak Master
124 Posts |
Posted - 2009-04-13 : 18:35:27
|
| Not quite the best solution for me since I cannot specify the first 5 digits as we did in our code. Our logic is similar and it all works just fine without too much stress on the database. Your solution should work pretty well. |
 |
|
|
|
|
|
|
|