2017-09-13 11 views
0

マッピングテーブルを使用し、ループを使用せずにSQL Serverの文字を文字列から置き換える方法はありますか?SQL - ループを使用せずにマッピングを使用して文字を置換する

私はこのように行くことができるマッピングを持っている:

a => b 
b => c 
... 
z => a 

このマッピングは、静的なものではなく、変更することができます。 私はhttps://stackoverflow.com/a/45202933/3161817https://stackoverflow.com/a/13051989/3161817から解決策を試してみましたが、私はばかりしている文字列を持つ終わる、「aaaaaaaa」のよう

私の現在のソリューションのようなものです:

DECLARE @NextChar NCHAR(1) 
DECLARE @Position int = 1 
DECLARE @StrLength int = LEN(@str) 
DECLARE @Result nvarchar(1000) = '' 

WHILE (@Position <= @StrLength) 
BEGIN 
    SET @NextChar = SUBSTRING(@str, @Position, 1) 

    SET @Result = @Result + ISNULL((SELECT ToChar FROM CharMapping 
            WHERE @NextChar COLLATE Latin1_General_BIN = FromChar COLLATE Latin1_General_BIN 
           ), @NextChar) 

    SET @Position= @Position + 1 
END 

が、私は探していますループのない可能な解決策。

+0

私はあなたが私のようではないマッピングテーブル内の任意の文字が残されるべきであることを追加している必要がありますUDF – LONG

+0

としてこれを作成することができますと言うでしょう。 abcdef-zz => bcdefg-aa また、マッピングを使用して大文字/小文字が正しく置き換えられるように、COLLATIONを使用する必要があります。 – pdube

答えて

2
DECLARE @t TABLE(
    src char 
,dest char 
) 

INSERT INTO @t VALUES 
('a', 'b') 
,('b', 'c') 
,('d', 'e') 

DECLARE @TestString nvarchar(100) = 'aabbcdacbezzz'; 

WITH cte AS(
    SELECT 1 lvl, SUBSTRING(@TestString, 1, 1) AS TestPosChar, SUBSTRING(@TestString, 2, LEN(@TestString)-1) AS TestStringRemain 
    UNION ALL 
    SELECT lvl + 1, SUBSTRING(TestStringRemain, 1, 1), SUBSTRING(TestStringRemain, 2, LEN(TestStringRemain)-1) 
    FROM cte 
    WHERE LEN(TestStringRemain) >= 1 
) 
SELECT @TestString AS OldString 
     ,SUBSTRING((SELECT ('' + ISNULL(t.dest, TestPosChar)) 
        FROM cte c 
        LEFT JOIN @t AS t ON t.src = c.TestPosChar 
        ORDER BY lvl 
        FOR XML PATH('') 
       ), 1, 1000) AS NewString 
1

私は、このテスト作っ:XMLパスを使用したクエリ以下

declare @MyTab table(
letter char 
) 

declare @MyTab2 table(
letter char 
) 

insert into @MyTab 
select substring(a.b, v.number+1, 1) 
from (select 'ABCDEFGHZZZ' b) a 
join master..spt_values v on v.number < len(a.b) 
where v.type = 'P' 

insert into @MyTab2 
select NewLetter 
from (
select case letter when 'Z' then 'A' 
    when 'z' then 'a' 
    else char(ascii(letter)+1) end NewLetter 
from @MyTab 
) MyView 

select stuff(
(select ''+letter from @MyTab2 
for xml path('')),1,0,'') 
1

てみてください(・拡大)、タリー番号テーブルとデコードテーブル:

CREATE TABLE #TTMMPP (ORIG CHAR(1), NEWC CHAR(1)); 
    /* add all values to shift */ 
     INSERT INTO #TTMMPP VALUES ('a','b'),('b','c'),('c','d'),('d','e'),('e','f') /*, ....*/ 
    ; 

    /* N as max len of your string */ 
    CREATE TABLE #TTMMPP2 (N smallint); 
    DECLARE @I INT 
    DECLARE @ROWS INT  
    SET @I = 1 
    SET @ROWS = 1000 
    WHILE @I < @ROWS 
    BEGIN 
    INSERT INTO #TTMMPP2 VALUES (@I) 
    SET @I = @I + 1 
    END 

    ----------------------------------------  
    DECLARE @my_str VARCHAR(100) = 'abcd'; 

    SELECT @my_str AS ORIGINAL, 
     (
      SELECT ''+C.NEWC 
        FROM (
         SELECT N, SUBSTRING(@my_str, N,1) AS X, B.NEWC 
         FROM #TTMMPP2 A 
         INNER JOIN #TTMMPP B ON SUBSTRING(@my_str,A.N,1)= B.ORIG 
         WHERE N<=LEN(@my_str) 
         ) C 
         FOR XML PATH('') 
         ) AS SHIFTED; 

出力:

ORIGINAL SHIFTED 
abcd bcde 

「マーク」文字をデコードタブに表示しない場合は、を更新してください。ルあなたは(照会する少しの変更:LEFT JOINをし、COALESCE):これを使用することができ

DECLARE @my_str VARCHAR(100) = 'abcdefg'; 
SELECT @my_str AS ORIGINAL, 
    (
     SELECT ''+C.NEWC 
       FROM (
        SELECT N, SUBSTRING(@my_str, N,1) AS X, COALESCE(B.NEWC,'*') AS NEWC 
        FROM #TTMMPP2 A 
        LEFT JOIN #TTMMPP B ON SUBSTRING(@my_str,A.N,1)= B.ORIG 
        WHERE N<=LEN(@my_str)     
        ) C 
        ORDER BY N 
        FOR XML PATH('') 
        ) AS SHIFTED; 

出力(デコードテーブルに見つからない*代替文字):

ORIGINAL SHIFTED 
abcdefg bcde*** 

新しいアップデートを(としてあなた最後のコメントは)追加:

SELECT @my_str AS ORIGINAL, 
    (
     SELECT ''+C.NEWC 
       FROM (
        SELECT N, SUBSTRING(@my_str, N,1) AS X, COALESCE(B.NEWC,SUBSTRING(@my_str,A.N,1)) AS NEWC 
        FROM ##TTMMPP2 A 
        LEFT JOIN #TTMMPP B ON SUBSTRING(@my_str,A.N,1) COLLATE Latin1_General_BIN = B.ORIG COLLATE Latin1_General_BIN 
        WHERE N<=LEN(@my_str)     
        ) C 
        ORDER BY N 
        FOR XML PATH('') 
        ) AS SHIFTED 

出力:

ORIGINAL SHIFTED 
abcdefgA bcdeefgA 
1

SQL Server 20107では、REPLACE機能と同様のa TRANSLATE functionが導入されています。使用しているSQL Serverのバージョンを指定していないので、そのオプションかどうかわかりません。

SELECT TRANSLATE(@SourceString, 'abcdefghijklmnopqrstuvwxyz', 'bcdefghijklmnopqrstuvwxyza'); 
+0

SQL 2012を使用しています。 – pdube

+0

@DanあなたはTRANSLATE()を意味します。REPLACE – etsa

+0

@etsaを書きました。 –

関連する問題