Более новые версии SQL Server имеют лучшие решения для этого, такие как встроенная функция Translate
, представленная в версии 2017 года.
Однако, поскольку это версия 2008 года, вам придется самостоятельно манипулировать строкой.
Мое предлагаемое решение состоит в том, чтобы использовать таблицу для переводов, не совсем такую же, как ответ ДхрувДжоши (я думаю, что мой проще), но очень похожий подход.
Сказав это, вот еще один подход, который вообще не использует replace
:
Сначала создайте и заполните образец таблицы ( Пожалуйста, сохраните этот шаг в ваших будущих вопросах):
DECLARE @T AS TABLE
(
Col nvarchar(32)
)
INSERT INTO @T (Col) VALUES
('952683174'),
('123456789'),
('06432') -- added more values to make sure I didn't mess it up
Затем создайте и заполните таблицу перевода:
DECLARE @Translate AS TABLE
(
original char(1),
translation char(1)
)
INSERT INTO @Translate (original, translation) VALUES
('1', '3'),
('2', '5'),
('3', '4'),
('4', '1'),
('5', '9'),
('6', '8'),
('7', '2'),
('8', '3'),
('9', '6')
Теперь, используя сложенный cte в качестве замены таблицы подсчета (конечно, вы можете использовать фактическую таблицу подсчета, если она у вас есть. Если нет, прочитайте таблицу «Числа» или «Подсчет» Джеффа Модена: Что и как он заменяет цикл ), cross apply
и левое соединение, чтобы выполнить перевод, и for xml path
как string_agg (еще одна функция, окончательно созданная в версии 2017 года), вы можете сделать это следующим образом:
;WITH E1(N) AS (SELECT 1 FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) V(v)), --10E+1 or 10 rows
E2(N) AS (SELECT 1 FROM E1 a CROSS JOIN E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a CROSS JOIN E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4)
SELECT Col,
(
SELECT ISNULL(translation, c)
FROM @T as t1
CROSS APPLY
(
SELECT Substring(Col, N, 1) As c, translation
FROM cteTally
LEFT JOIN @Translate ON Substring(Col, N, 1) = original
WHERE N <= LEN(ISNULL(Col, ''))
) as t2
WHERE t1.Col = t0.Col
FOR XML PATH('')
) As translated
FROM @T t0
Результаты:
col translated
952683174 695834321
123456789 354198236
06432 08145 -- Note that the 0 doesn't get translated...
Вы можете увидеть живое демо на rextester.
Основные преимущества моего решения по сравнению с другим ответом, предоставленным в настоящее время:
- Подход, основанный на всех наборах, без использования замены или манипуляции со строками.
- Все переводы хранятся в виде табличных значений. Ничто не жестко закодировано.
- Значения перевода не ограничены одним символом. Если вы решите перевести 9 на 11, вам потребуется только изменить таблицу перевода (ответ MatSnow также имеет это преимущество)