您可以使用Recursive CTE 来递归应用REPLACE 函数:
;WITH StripSpecialChars AS (
SELECT id, 0 AS lvl,
[EpiNum] = REPLACE([EpiNum], SUBSTRING([EpiNum], x.i, 1), ''),
[Name] = REPLACE([Name], SUBSTRING([Name], y.i, 1), ''),
[Acct] = REPLACE([Acct], SUBSTRING([Acct], z.i, 1), '')
FROM TableA
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [EpiNum])) AS x(i)
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [Name])) AS y(i)
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [Acct])) AS z(i)
WHERE x.i <> 0 OR y.i <> 0 OR z.i <> 0
UNION ALL
SELECT id, lvl = lvl + 1,
[EpiNum] = REPLACE([EpiNum], SUBSTRING([EpiNum], x.i, 1), ''),
[Name] = REPLACE([Name], SUBSTRING([Name], y.i, 1), ''),
[Acct] = REPLACE([Acct], SUBSTRING([Acct], z.i, 1), '')
FROM StripSpecialChars
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [EpiNum])) AS x(i)
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [Name])) AS y(i)
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [Acct])) AS z(i)
WHERE x.i <> 0 OR y.i <> 0 OR z.i <> 0
)
只要没有更多的特殊字符要替换,CTE 就会终止。
每个id 具有最大lvl 值的行是包含[EpiNum]、[Name]、[Acct] 字段的精简值的行。因此,您可以使用以下代码在单个 SQL 语句中执行 UPDATE:
;WITH StripSpecialChars AS (
... above query here ...
)
UPDATE t1
SET t1.[EpiNum] = t2.[EpiNum],
t1.[Name] = t2.[Name],
t1.[Acct] = t2.[Acct]
FROM TableA AS t1
INNER JOIN (SELECT id, [EpiNum], [Name], [Acct],
ROW_NUMBER() OVER (PARTITION BY id
ORDER BY lvl DESC) AS rn
From StripSpecialChars) AS t2
ON t1.id = t2.id AND t2.rn = 1
Demo here
编辑:
如果TableA中没有PK列,那么你可以将你的表包裹在CTE中,使用ROW_NUMBER模拟PK,最后在CTE上执行更新:
;WITH TableA_PK AS (
SELECT [EpiNum], [Name], [Acct],
ROW_NUMBER() OVER (ORDER BY [EpiNum]) AS id
FROM TableA
), StripSpecialChars AS (
SELECT id, 0 AS lvl,
[EpiNum] = REPLACE([EpiNum], SUBSTRING([EpiNum], x.i, 1), ''),
[Name] = REPLACE([Name], SUBSTRING([Name], y.i, 1), ''),
[Acct] = REPLACE([Acct], SUBSTRING([Acct], z.i, 1), '')
FROM TableA_PK
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [EpiNum])) AS x(i)
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [Name])) AS y(i)
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [Acct])) AS z(i)
WHERE x.i <> 0 OR y.i <> 0 OR z.i <> 0
UNION ALL
SELECT id, lvl = lvl + 1,
[EpiNum] = REPLACE([EpiNum], SUBSTRING([EpiNum], x.i, 1), ''),
[Name] = REPLACE([Name], SUBSTRING([Name], y.i, 1), ''),
[Acct] = REPLACE([Acct], SUBSTRING([Acct], z.i, 1), '')
FROM StripSpecialChars
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [EpiNum])) AS x(i)
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [Name])) AS y(i)
CROSS APPLY (SELECT PATINDEX('%[^a-zA-Z0-9 ]%', [Acct])) AS z(i)
WHERE x.i <> 0 OR y.i <> 0 OR z.i <> 0
)
UPDATE t1
SET t1.[EpiNum] = t2.[EpiNum],
t1.[Name] = t2.[Name],
t1.[Acct] = t2.[Acct]
FROM TableA_PK AS t1
INNER JOIN (SELECT id, [EpiNum], [Name], [Acct],
ROW_NUMBER() OVER (PARTITION BY id
ORDER BY lvl DESC) AS rn
FROM StripSpecialChars) AS t2
ON t1.id = t2.id AND t2.rn = 1
Demo here