有没有办法使用映射表从字符串中替换SQL Server中的字符,而不使用循环。
我的映射可以像这样:
a => b
b => c
...
z => a
此映射不是静态的,可以更改。 我尝试了https://stackoverflow.com/a/45202933/3161817和https://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 :(得分:1)
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 :(得分:0)
我做了这个测试:
setup(
…
scripts=["main.py"],
…
)
答案 2 :(得分:0)
尝试(并展开)以下查询,它使用XML PATH,一个计数表和一个解码表:
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
答案 3 :(得分:0)
SQL Server 2017引入了a TRANSLATE
function,它类似于嵌套的REPLACE
函数。您没有指定您正在使用的SQL Server版本,所以我不知道这是否是一个选项。
SELECT TRANSLATE(@SourceString, 'abcdefghijklmnopqrstuvwxyz', 'bcdefghijklmnopqrstuvwxyza');