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 |
|
erwine
Yak Posting Veteran
69 Posts |
Posted - 2006-05-19 : 02:43:21
|
| Hi everybody..Let's say i have @parameter = '0001'Im thinking of writing a function to increment the parameter.This is how it should work:@parameter + 8 = '0009'@parameter + 9 = '000A'@parameter + 11 = '000B'@parameter + 34 = '000Z'@parameter + 35 = '0010''001A' + 20 = '001U'something like this? anyone has ideas??... sql is fun... |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2006-05-19 : 02:49:27
|
What do you want to achieve ?Do you need to pass unknown number of parameters into the Stored Procedure ? KH |
 |
|
|
erwine
Yak Posting Veteran
69 Posts |
Posted - 2006-05-19 : 02:57:55
|
| basically i will have :declare @parameter varchar(4)then i wanna do:select A.*, @@identity, Function1(@@identity + @parameter)... sql is fun... |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-05-19 : 03:20:07
|
| It seems that you need a BASE 36 calculator. Also there is an error in your supplied example code! @parameter + 11 = '000B' is wrong! Should be @parameter + 11 = '000C'Anyway, here is the function to achieve the result you are looking for:--------------------------------------------------------Call function with SELECT dbo.fnBase36('001A', 20)--------------------------------------------------------CREATE FUNCTION dbo.fnBase36( @OldNumber VARCHAR(4), @NewValue INT)RETURNS VARCHAR(4)ASBEGIN IF @OldNumber IS NULL OR @OldNumber = '' OR LEN(@OldNumber) > 4 RETURN NULL DECLARE @Base36 VARCHAR(36), @Base INT, @Index INT, @CharValue INT, @Sum INT SELECT @Base36 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', @Index = LEN(@OldNumber), @Base = 1, @Sum = 0 WHILE @Index > 1 BEGIN SELECT @CharValue = CHARINDEX(SUBSTRING(@OldNumber, @Index, 1), @Base36) - 1 IF @CharValue < 0 RETURN NULL SELECT @Sum = @Sum + @Base * @CharValue, @Base = @Base * 36, @Index = @Index - 1 END IF @Sum + @NewValue > 1679615 RETURN NULL SELECT @OldNumber = '', @Base = 46656, @Sum = @Sum + @NewValue WHILE @Base > 0 BEGIN SELECT @Index = @Sum / @Base SELECT @OldNumber = @OldNumber + SUBSTRING(@Base36, @Index + 1, 1), @Sum = @Sum - @Index * @Base, @Base = @Base / 36 END RETURN RIGHT('0000' + @OldNumber, 4)END |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-05-19 : 03:23:17
|
quote: Originally posted by khtan Still not sure why you want to do this.The only way is using Dynamic SQL KH
No, you don't have to resort to dynamic SQL. Some basic math is required, that's all. It's called Base Converting.Erwine, use this code for your result!------------------------------------------------declare @parameter varchar(4)then i wanna do:select A.*, @@identity, dbo.fnBase36(@parameter, @@identity) |
 |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2006-05-19 : 03:26:00
|
quote: Originally posted by Peso
quote: Originally posted by khtan Still not sure why you want to do this.The only way is using Dynamic SQL KH
No, you don't have to resort to dynamic SQL. Some basic math is required, that's all. It's called Base Converting.Erwine, use this code for your result!------------------------------------------------declare @parameter varchar(4)then i wanna do:select A.*, @@identity, dbo.fnBase36(@parameter, @@identity)
Miss interpret the requirement  KH |
 |
|
|
erwine
Yak Posting Veteran
69 Posts |
Posted - 2006-05-19 : 03:31:30
|
| Thx PESO..it's nice.it works perfectly for 4digits..however it has problem with arithmetic overflows when i try with 10digits.... sql is fun... |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-05-19 : 03:38:03
|
| You mean like this?ALTER FUNCTION dbo.fnBase36( @OldNumber VARCHAR(10), @NewValue BIGINT)RETURNS VARCHAR(10)ASBEGIN IF @OldNumber IS NULL OR LEN(@OldNumber) < 1 OR LEN(@OldNumber) > 4 RETURN NULL DECLARE @Base36 VARCHAR(36), @Base BIGINT, @Index TINYINT, @CharValue TINYINT, @Sum BIGINT SELECT @Base36 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', @Index = LEN(@OldNumber), @Base = 1, @Sum = 0 WHILE @Index > 1 BEGIN SELECT @CharValue = CHARINDEX(SUBSTRING(@OldNumber, @Index, 1), @Base36) - 1 IF @CharValue < 0 RETURN NULL SELECT @Sum = @Sum + @Base * @CharValue, @Base = @Base * 36, @Index = @Index - 1 END IF @Sum + @NewValue >= CONVERT(BIGINT, POWER(36.0, 10.0)) RETURN NULL SELECT @OldNumber = '', @Base = CONVERT(BIGINT, POWER(36.0, 9.0)), @Sum = @Sum + @NewValue WHILE @Base > 0 BEGIN SELECT @Index = @Sum / @Base SELECT @OldNumber = @OldNumber + SUBSTRING(@Base36, @Index + 1, 1), @Sum = @Sum - @Index * @Base, @Base = @Base / 36 END RETURN RIGHT('0000000000' + @OldNumber, 10)END |
 |
|
|
erwine
Yak Posting Veteran
69 Posts |
Posted - 2006-05-19 : 03:40:08
|
| oo icic..so it BIGINT..get it..thx so much peso.thanks to khtan as well for some advices. :pcheers,erwine... sql is fun... |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-05-19 : 03:40:42
|
| Sorry, missed a "> 4". Should by "> 10"...ALTER FUNCTION dbo.fnBase36(@OldNumber VARCHAR(10),@NewValue BIGINT)RETURNS VARCHAR(10)ASBEGINIF @OldNumber IS NULL OR LEN(@OldNumber) < 1 OR LEN(@OldNumber) > 10RETURN NULLDECLARE @Base36 VARCHAR(36),@Base BIGINT,@Index TINYINT,@CharValue TINYINT,@Sum BIGINTSELECT @Base36 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',@Index = LEN(@OldNumber),@Base = 1,@Sum = 0WHILE @Index > 1BEGINSELECT @CharValue = CHARINDEX(SUBSTRING(@OldNumber, @Index, 1), @Base36) - 1IF @CharValue < 0RETURN NULLSELECT @Sum = @Sum + @Base * @CharValue,@Base = @Base * 36,@Index = @Index - 1ENDIF @Sum + @NewValue >= CONVERT(BIGINT, POWER(36.0, 10.0))RETURN NULLSELECT @OldNumber = '',@Base = CONVERT(BIGINT, POWER(36.0, 9.0)),@Sum = @Sum + @NewValueWHILE @Base > 0BEGINSELECT @Index = @Sum / @BaseSELECT @OldNumber = @OldNumber + SUBSTRING(@Base36, @Index + 1, 1),@Sum = @Sum - @Index * @Base,@Base = @Base / 36ENDRETURN RIGHT('0000000000' + @OldNumber, 10)END |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-05-19 : 03:49:01
|
| Final version! Missed a bug when not having a leading zero for parameter...CREATE FUNCTION dbo.fnBase36( @OldNumber VARCHAR(10), @NewValue BIGINT)RETURNS VARCHAR(10)ASBEGIN IF @OldNumber IS NULL OR LEN(@OldNumber) < 1 OR LEN(@OldNumber) > 10 RETURN NULL DECLARE @Base36 VARCHAR(36), @Base BIGINT, @Index TINYINT, @CharValue TINYINT, @Sum BIGINT SELECT @Base36 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', @Index = LEN(@OldNumber), @Base = 1, @Sum = 0 WHILE @Index > 0 BEGIN SELECT @CharValue = CHARINDEX(SUBSTRING(@OldNumber, @Index, 1), @Base36) - 1 IF @CharValue < 0 RETURN NULL SELECT @Sum = @Sum + @Base * @CharValue, @Base = @Base * 36, @Index = @Index - 1 END IF @Sum + @NewValue >= CONVERT(BIGINT, POWER(36.0, 10.0)) RETURN NULL SELECT @OldNumber = '', @Base = CONVERT(BIGINT, POWER(36.0, 9.0)), @Sum = @Sum + @NewValue WHILE @Base > 0 BEGIN SELECT @Index = @Sum / @Base SELECT @OldNumber = @OldNumber + SUBSTRING(@Base36, @Index + 1, 1), @Sum = @Sum - @Index * @Base, @Base = @Base / 36 END RETURN RIGHT('0000000000' + @OldNumber, 10)END |
 |
|
|
erwine
Yak Posting Veteran
69 Posts |
Posted - 2006-05-19 : 03:50:52
|
| ALTER FUNCTION dbo.fnBase36( @Old VARCHAR(8), @New BIGINT)RETURNS VARCHAR(8)ASBEGINIF @Old IS NULL OR LEN(@Old) < 1 OR LEN(@Old) > 8RETURN NULLDECLARE @Base36 VARCHAR(36), @Base BIGINT, @Index TINYINT, @CharValue TINYINT, @Sum BIGINTSELECT @Base36 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', @Index = LEN(@Old), @Base = 1, @Sum = 0WHILE @Index > 1BEGINSELECT @CharValue = CHARINDEX(SUBSTRING(@Old, @Index, 1), @Base36) - 1IF @CharValue < 0RETURN NULLSELECT @Sum = @Sum + @Base * @CharValue, @Base = @Base * 36, @Index = @Index - 1ENDIF @Sum + @New >= CONVERT(BIGINT, POWER(36.0, 8.0))RETURN NULLSELECT @Old = '', @Base = CONVERT(BIGINT, POWER(36.0, 7.0)), @Sum = @Sum + @NewWHILE @Base > 0BEGINSELECT @Index = @Sum / @BaseSELECT @Old = @Old + SUBSTRING(@Base36, @Index + 1, 1), @Sum = @Sum - @Index * @Base, @Base = @Base / 36ENDRETURN RIGHT('00000000' + @Old, 8)ENDthis code's for 8digits, which is the one that i want to do.however it doesnt give correct answer forselect dbo.fnBase36('921001A1', 100) as testis it because BIGINT is not big enough??... sql is fun... |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-05-19 : 03:59:13
|
| No, I get '921001CT' as result with my final version of dbo.fnBase36Just change "WHILE @Index > 1" to "WHILE @Index > 0" ! |
 |
|
|
erwine
Yak Posting Veteran
69 Posts |
Posted - 2006-05-19 : 04:00:47
|
| ya..i just finished changing it to >=1 hahahahathx thx..... sql is fun... |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-05-19 : 04:01:31
|
| CREATE FUNCTION dbo.fnBase36( @OldNumber VARCHAR(8), @NewValue BIGINT)RETURNS VARCHAR(8)ASBEGIN IF @OldNumber IS NULL OR LEN(@OldNumber) < 1 OR LEN(@OldNumber) > 8 RETURN NULL DECLARE @Base36 VARCHAR(36), @Base BIGINT, @Index TINYINT, @CharValue TINYINT, @Sum BIGINT SELECT @Base36 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', @Index = LEN(@OldNumber), @Base = 1, @Sum = 0 WHILE @Index > 0 BEGIN SELECT @CharValue = CHARINDEX(SUBSTRING(@OldNumber, @Index, 1), @Base36) - 1 IF @CharValue < 0 RETURN NULL SELECT @Sum = @Sum + @Base * @CharValue, @Base = @Base * 36, @Index = @Index - 1 END IF @Sum + @NewValue >= CONVERT(BIGINT, POWER(36.0, 8)) RETURN NULL SELECT @OldNumber = '', @Base = CONVERT(BIGINT, POWER(36.0, 7)), @Sum = @Sum + @NewValue WHILE @Base > 0 BEGIN SELECT @Index = @Sum / @Base SELECT @OldNumber = @OldNumber + SUBSTRING(@Base36, @Index + 1, 1), @Sum = @Sum - @Index * @Base, @Base = @Base / 36 END RETURN RIGHT('00000000' + @OldNumber, 8)END |
 |
|
|
RyanRandall
Master Smack Fu Yak Hacker
1074 Posts |
Posted - 2006-05-19 : 08:13:03
|
Hi all,You can create generalised version (i.e. for base N ) with the functions below. Here are a few example calls:SELECT dbo.fnAddBaseN('921001A1', 100, 36) as 'Equals 921001CT'SELECT dbo.fnAddBaseN('12345', 100, 10) as 'Equals 12445'SELECT dbo.fnAddBaseN('101', 100, 2) as 'Equals 1101001'The first 2 functions were taken from this very (very) useful resource:http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=502&lngWId=5CREATE function DECTON(@n bigint, @b int)--Converts a decimal number to base n.returns varchar(255)asBEGINDECLARE @i bigint,@temp int, @s varchar(255)SET @i=@nSET @s=''WHILE (@i>0)BEGIN SET @temp=@i % @b SET @i=@i /@b IF @temp>9 SET @s=char(55+@temp)+@s ELSE SET @s=char(48+@temp)+@sENDRETURN @sENDgoCREATE function NTODEC(@s VARCHAR(255), @b bigint) --Converts a number on base n to decimal.returns bigintasBEGINDECLARE @i int, @temp char(1), @result bigintSELECT @i=1SELECT @result=0WHILE (@i<=LEN(@s))BEGIN SELECT @temp=UPPER(SUBSTRING(@s,@i,1)) IF (@temp>='0') AND (@temp<='9') SELECT @result=@result+ (ASCII(@temp)-48)*POWER(@b,LEN(@s)-@i) ELSE SELECT @result=@result+ (ASCII(@temp)-55)*POWER(@b,LEN(@s)-@i) SELECT @i=@i+1ENDreturn @resultENDgoCREATE FUNCTION dbo.fnAddBaseN(@BaseNValue VARCHAR(10), @DecValue BIGINT, @Base INT)RETURNS VARCHAR(10) ASBEGIN RETURN dbo.DECTON(dbo.NTODEC(@BaseNValue, @Base) + @DecValue, @Base)ENDgo Ryan Randallwww.monsoonmalabar.com London-based IT consultancy Solutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
|
|
|
|
|