Reputation: 4505
Getting this done in C# would have been such an easy task, but I am required to do this in sql. Basically, I need to write a tsql function that would convert a given varchar to it's corresponding encoding. For instance, if an input is '123456789' our business rule requires it be converted to 'ABCDEFGHI.' In short, I am trying to convert below c# code to tsql:
class Program
{
static void Main(string[] args)
{
string a = "1234567890";
char[] oldA = a.ToCharArray();
char[] newA = new char[10];
for (int i =0; i<oldA.Length; i++)
{
switch (oldA[i])
{
case '1':
newA[i] = 'A';
break;
case '2':
newA[i] = 'B';
break;
//and so on..
}
}
Console.WriteLine(newA);
Console.ReadKey();
}
}
I am confirmed that there is no array like thing in tsql, and most of the answers I came across assumed that it had some kind of delimiter to it, so wasn't particularly very useful.
Thanks.
Upvotes: 0
Views: 5076
Reputation: 12015
Based on peterm's second option (if it is safe to assume that all chars in the input will be between '0' and 9'):
CREATE FUNCTION myfunc2(@expr AS VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
DECLARE @i AS INT = 1, @chr CHAR(1), @result VARCHAR(255) = ''
WHILE @i <= LEN(@expr)
BEGIN
SET @chr = SUBSTRING(@expr, @i, 1)
SET @result = @result +
CASE @chr
WHEN '0' THEN 'J'
ELSE CHAR(64 + cast(@chr as int))
END
SET @i = @i + 1
END -- WHILE
RETURN @result
END
Or, possibly more efficient, since reduces the number of CAST calls:
CREATE FUNCTION myfunc2(@expr AS VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
DECLARE @i AS INT = 1, @b1 BINARY(1), @result VARCHAR(255) = ''
declare @b VARBINARY(255)
SET @b = CAST(@expr as VARBINARY(255))
WHILE @i <= LEN(@b)
BEGIN
SET @b1 = SUBSTRING(@b, @i, 1)
SET @result = @result +
CASE @b1
WHEN 48 THEN 'J' -- 48 is ascii '0'
ELSE CHAR(16 + @b1) -- to get from '1' to 'A' on ASCII chart, need to add 16.
END
SET @i = @i + 1
END -- WHILE
RETURN @result
END
Upvotes: 0
Reputation: 92795
You can do either
CREATE FUNCTION myfunc(@expr AS VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
RETURN REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(@expr, '1', 'A'),
'2', 'B')
'3', 'C'),
'4', 'D'),
'5','E'),
'6', 'F'),
'7', 'G'),
'8', 'H'),
'9', 'I'),
'0','J')
END
or (which is much closer to what you've got in C#)
CREATE FUNCTION myfunc2(@expr AS VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
DECLARE @i AS INT = 1, @chr CHAR(1), @result VARCHAR(255) = ''
WHILE @i <= LEN(@expr)
BEGIN
SET @chr = SUBSTRING(@expr, @i, 1)
SET @result = @result +
CASE @chr
WHEN '1' THEN 'A'
WHEN '2' THEN 'B'
WHEN '3' THEN 'C'
WHEN '4' THEN 'D'
WHEN '5' THEN 'E'
WHEN '6' THEN 'F'
WHEN '7' THEN 'G'
WHEN '8' THEN 'H'
WHEN '9' THEN 'I'
WHEN '0' THEN 'J'
ELSE @chr
END
SET @i = @i + 1
END -- WHILE
RETURN @result
END
Sample usage for both functions:
SELECT dbo.myfunc(value) result, dbo.myfunc2(value) result2
FROM
(
VALUEs ('1234567890'), ('5512314567')
) t(value);
Sample output:
| RESULT | RESULT2 | |------------|------------| | ABCDEFGHIJ | ABCDEFGHIJ | | EEABCADEFG | EEABCADEFG |
Here is a SQLFiddle demo
Upvotes: 3
Reputation: 19194
Here is a function that I put in most databases that I work with:
CREATE FUNCTION [dbo].[f_ForLoop](@Start INT , @End INT, @Increment INT = 1)
RETURNS @Loop TABLE
(
RowNumber INT
)
AS
--=============================================================
-- f_ForLoop
--
-- DATE AUTHOR DESCRIPTION
-- 17 Apr 2012 Nick McDermaid Created
--
-- PURPOSE:
-- Return a table that can be joined to with the number of records indicated in parameters
--
-- USAGE:
-- SELECT RowNumber FROM dbo.f_ForLoop(1,10,1)
-- SELECT RowNumber FROM dbo.f_ForLoop(10,1,-1)
-- SELECT RowNumber FROM dbo.f_ForLoop(2,20,2)
--=============================================================
BEGIN
IF @Increment = 0 RETURN
IF @Increment < 0 AND @Start < @End RETURN
IF @Increment > 0 AND @Start > @End RETURN
IF @Increment IS NULL SET @Increment = 1
WHILE NOT (@Start = @End)
BEGIN
INSERT INTO @Loop (RowNumber) VALUES (@Start)
SET @Start = @Start + @Increment
END
INSERT INTO @Loop (RowNumber) VALUES (@Start)
RETURN
END
Then you can use it something like this:
DECLARE @YourString VARCHAR(50)
SET @YourString='ABCDEFGHIJ'
SELECT
RowNumber,
SUBSTRING(@YourString,RowNumber,1) As Token,
ASCII(SUBSTRING(@YourString,RowNumber,1)) - 64 Result
FROM dbo.f_ForLoop(1,LEN(@YourString),1)
This is not exactly what you're after but serves to highlight some functionality.
The next step is to join to a mapping table instead of using ASCII because clearly this is not what you're after. This of course assume that one character is one token.
Upvotes: 0