2014-01-28 3 views
0

Выполнение этого в C# было бы такой простой задачей, но я должен сделать это в sql. В принципе, мне нужно написать функцию tsql, которая преобразует данный varchar в соответствующую кодировку. Например, если ввод «123456789», наше бизнес-правило требует его преобразования в «ABCDEFGHI». Короче говоря, я пытаюсь преобразовать ниже C# кода TSQL:Преобразование строки в массив символов или альтернативу - 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, и большинство ответов я наткнулся предположил, что это был какой-то разделителем к этому, поэтому было не особенно полезно.

Спасибо.

+1

как вы кодируете Z? это 26? Откуда вы знаете, что это не BF? Это довольно легко сделать в SQL –

+0

Существует массив вроде вещи - это называется таблицей! –

+0

@ElectricLlama: вход всегда будет числовым и будет закодирован в соответствующий алфавит, определенный некоторым правилом, поэтому кодирование Z не будет необходимо для моего сценария. Что такое BF? Итак, как мне разделить заданную строку на символы и поместить каждый символ в строку? Любая ссылка с примером, на который вы могли бы указать? – NoSaidTheCompiler

ответ

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 демо

+0

Спасибо! Это, во-вторых, очень похоже на то, что я ищу. Ура! – NoSaidTheCompiler

+0

IMHO, если вы должны были реализовать это «правильно в базе данных, вы преобразовали бы все эти операторы CASE в записи в таблице. Это зависит от того, будете ли вы после решения, ориентированного на код, или централизованного решения базы данных. –

+0

@ ElectricLlama Определите * правильно *. ИМХО это не ориентация, а скорее требования и простота, и как можно более сухие. Но спасибо за ваш вклад. – peterm

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, потому что ясно, что это не то, что вам нужно. Это, конечно, предполагает, что один символ - это один токен.

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 
Смежные вопросы