将String转换为字符数组或替代 - Tsql

时间:2014-01-28 22:25:49

标签: sql-server-2008 tsql

在C#中完成这项工作将是一项非常简单的任务,但我需要在sql中执行此操作。基本上,我需要编写一个tsql函数,将给定的varchar转换为相应的编码。例如,如果输入为“123456789”,则我们的业务规则要求将其转换为“ABCDEFGHI”。简而言之,我试图将下面的c#代码转换为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();

    }
}

我确认在tsql中没有类似数组的东西,我遇到的大多数答案都假设它有某种分隔符,所以不是特别有用。

感谢。

3 个答案:

答案 0 :(得分:3)

你可以做任何一次

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

或(这与你在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

两种功能的示例用法:

SELECT dbo.myfunc(value) result, dbo.myfunc2(value) result2
  FROM
(
  VALUEs ('1234567890'), ('5512314567')
) t(value);

示例输出:

|     RESULT |    RESULT2 |
|------------|------------|
| ABCDEFGHIJ | ABCDEFGHIJ |
| EEABCADEFG | EEABCADEFG |

这是 SQLFiddle 演示

答案 1 :(得分:0)

这是我在大多数与之合作的数据库中放置的函数:

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

然后你可以使用这样的东西:

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)

这不完全是你所追求的,但却突出了一些功能。

下一步是加入映射表而不是使用ASCII,因为很明显这不是你想要的。这当然假设一个字符是一个标记。

答案 2 :(得分:0)

基于peterm的第二个选项(如果可以安全地假设输入中的所有字符都在'0'和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

或者,可能更有效,因为减少了CAST呼叫的数量:

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