我试图在SQL Server查询中替换多个字符,并希望通过#temp表而不是嵌套的REPLACE来实现。我在下面得到了SQL代码,想要实现像
这样的结果ABCGHI
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL DROP TABLE #temp2
CREATE TABLE #temp
(
STRING_TO_REPLACE NVARCHAR(5)
)
INSERT INTO #temp (STRING_TO_REPLACE)
VALUES (' ')
,('/')
,('_')
CREATE TABLE #temp2
(
STRING_NAME NVARCHAR(5)
)
INSERT INTO #temp2 (STRING_NAME)
VALUES ('A BC')
,('D/EF')
,('G_HI')
SELECT REPLACE(t2.STRING_NAME,(SELECT t1.STRING_TO_REPLACE
FROM #temp t1),'')
FROM #temp2 t2
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL DROP TABLE #temp2
我可以用嵌套替换
来实现结果SELECT REPLACE(REPLACE(REPLACE(t2.STRING_NAME,'_',''),'/',''),' ','') FROM #temp2 t2
但是真的想通过#temp表来做到这一点。请有人帮我这个。 当我尝试运行我的第一个代码时,我收到以下错误
Msg 512,Level 16,State 1,Line 23子查询返回超过1 值。当子查询遵循=,!=,<,< =,
时,不允许这样做,> =或当子查询用作表达式时。
答案 0 :(得分:5)
以下是使用CROSS APPLY
SELECT result
FROM #temp2 t2
CROSS apply (SELECT Replace(string_name, t1.string_to_replace, '') AS
result
FROM #temp t1) cs
WHERE result <> string_name
结果:
result
-----
ABC
DEF
GHI
注意:仅当每个string_name
只有一个string_to_replace
更新:要在一个string_to_replace
中处理多个string_name
,这是使用Dynamic sql
的一种方法
我通过添加#temp
属性来循环
identity
表进行了一处小改动
IF Object_id('tempdb..#temp') IS NOT NULL
DROP TABLE #temp
IF Object_id('tempdb..#temp2') IS NOT NULL
DROP TABLE #temp2
CREATE TABLE #temp
(
id INT IDENTITY(1, 1),
string_to_replace NVARCHAR(5)
)
INSERT INTO #temp
(string_to_replace)
VALUES (' '),
('/'),
('_')
CREATE TABLE #temp2
(
string_name NVARCHAR(5)
)
INSERT INTO #temp2
(string_name)
VALUES ('A BC'),
('D/EF'),
('G_HI'),
('A BD_')
DECLARE @col_list VARCHAR(8000)= '',
@sql VARCHAR(max),
@cntr INT,
@inr INT =1,
@STRING_TO_REPLACE NVARCHAR(5)
SELECT @cntr = Max(id)
FROM #temp
SET @sql = 'select '
WHILE @inr < = @cntr
BEGIN
SELECT @STRING_TO_REPLACE = string_to_replace
FROM #temp
WHERE id = @inr
IF @inr = 1
SET @col_list = 'replace (STRING_NAME,'''
+ @STRING_TO_REPLACE + ''','''')'
ELSE
SET @col_list = 'replace (' + @col_list + ','''
+ @STRING_TO_REPLACE + ''','''')'
SET @inr+=1
END
SET @sql += ' from #temp2'
--print @col_list
SET @sql = 'select ' + @col_list + ' as Result from #temp2'
--print @sql
EXEC (@sql)
结果:
Result
------
ABC
DEF
GHI
ABD
答案 1 :(得分:1)
可以通过递归CTE实现多次替换,如下例所示:
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL DROP TABLE #temp2
CREATE TABLE #temp
(
STRING_TO_REPLACE NVARCHAR(10)
,Pattern NVARCHAR(10)
)
INSERT INTO #temp (STRING_TO_REPLACE, Pattern)
VALUES (' ', '% %')
,('/', '%/%')
,('_', '%[_]%') ;
CREATE TABLE #temp2
(
STRING_NAME NVARCHAR(10)
);
INSERT INTO #temp2 (STRING_NAME)
VALUES ('A BC')
,('D/EF_F E')
,('G_HI')
,('XYZ');
WITH CTE_Replace AS
(
SELECT STRING_NAME AS OriginalString
,CAST(STRING_NAME AS NVARCHAR(10)) AS ReplacedString
,CAST('' AS NVARCHAR(10)) AS StringToReplace
,1 AS ReplaceCount
FROM #temp2 ancor
UNION ALL
SELECT CTE_Replace.OriginalString
,CAST(REPLACE(CTE_Replace.ReplacedString, rep.STRING_TO_REPLACE, '') AS NVARCHAR(10)) AS ReplacedString
,CAST(rep.STRING_TO_REPLACE AS NVARCHAR(10)) AS StringToReplace
,CTE_Replace.ReplaceCount + 1 AS ReplaceCount
FROM #temp rep
INNER JOIN CTE_Replace ON CTE_Replace.ReplacedString LIKE rep.Pattern
)
,CTE_FinalReplacedString AS
(
SELECT OriginalString
,ReplacedString
,ReplaceCount
,ROW_NUMBER() OVER (PARTITION BY OriginalString ORDER BY ReplaceCount DESC) AS [Rank]
FROM CTE_Replace
)
SELECT *
FROM CTE_FinalReplacedString
WHERE [Rank] = 1
请注意,#temp
表已更新为包含一个名为Pattern
的额外列,此列包含要用于查找必须替换的特定字符串的搜索模式。这也是为了简化递归CTE中的join语句。另请注意,为了找到_
字符,搜索模式必须更新为'%[_]%'
。这是因为SQL Server会将_
字符解释为野生字符,而不是我们要查找的特定字符。
答案 2 :(得分:0)
表格中的替换可能更容易
update t2
set t2.string_name = Replace(t2.string_name, t1.string_to_replace, '')
from #temp2 t2
cross join #temp1 t1
答案 3 :(得分:0)
递归CTE的另一种方式(下面的完整批次):
--Create a sample table, you should use YourTable
CREATE TABLE #temp2 (
STRING_NAME NVARCHAR(max)
)
INSERT INTO #temp2 (STRING_NAME)
VALUES ('A BC'),('D/EF'),('G_HI'),('J_K/L_'),('MNO')
--I add some more objects here
主要查询:
;WITH replacement AS (
SELECT *
FROM (VALUES (' '),('/'),('_')
) as t(STRING_TO_REPLACE)
), cte AS (
SELECT STRING_NAME,
STRING_NAME as OriginalString,
ROW_NUMBER() OVER (ORDER BY STRING_NAME) as rn,
1 as [Level]
FROM #temp2 t2
UNION ALL
SELECT REPLACE(c.STRING_NAME,t.STRING_TO_REPLACE,'~'),
c.OriginalString,
c.rn,
[Level]+1
FROM cte c
INNER JOIN replacement t
ON CHARINDEX(t.STRING_TO_REPLACE,c.STRING_NAME,0) > 0
)
SELECT TOP 1 WITH TIES OriginalString,
STRING_NAME
FROM cte
ORDER BY ROW_NUMBER() OVER (PARTITION BY rn ORDER BY [Level] DESC)
OPTION (MAXRECURSION 0)
输出:
OriginalString STRING_NAME
A BC A~BC
D/EF D~EF
J_K/L_ J~K~L~
G_HI G~HI
MNO MNO
答案 4 :(得分:0)
处理此问题的一种简单方法是下载PatExclude8K的副本,这是一种专为此类任务而设计的T-SQL函数。以下是几个例子:
-- remove all non-aplphabetical characters
SELECT NewString FROM #temp2 CROSS APPLY dbo.PatExclude8K(STRING_NAME,'[^A-Z]');
-- remove all spaces, forward slashes and underscores
SELECT NewString FROM #temp2 CROSS APPLY dbo.PatExclude8K(STRING_NAME,'[ /_]');
两个查询都生成此结果集:
NewString
------------
ABC
DEF
GHI
答案 5 :(得分:0)
我在stackoverflow上找到了下面的代码,它似乎更接近我正在尝试实现的内容但我正在努力解决我如何在代码中使用它
declare @String varchar(max) = '(N_100-(6858)*(6858)*N_100/0_2)%N_35'
--table containing values to be replaced
create table #Replace
(
StringToReplace varchar(100) not null primary key clustered
,ReplacementString varchar(100) not null
)
insert into #Replace (StringToReplace, ReplacementString)
values ('+', '~')
,('-', '~')
,('*', '~')
,('/', '~')
,('%', '~')
,('(', '~')
,(')', '~')
select @String = replace(@String, StringToReplace, ReplacementString)
from #Replace a
select @String
drop table #Replace
gofr1 编辑
CREATE FUNCTION replacement
(
@String nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE @Replace TABLE (
StringToReplace nvarchar(100),
ReplacementString nvarchar(100)
)
INSERT INTO @Replace (StringToReplace, ReplacementString)
VALUES ('+', '~')
,('-', '~')
,('*', '~')
,('/', '~')
,('%', '~')
,('(', '~')
,(')', '~')
SELECT @String = replace(@String, StringToReplace, ReplacementString)
FROM @Replace
RETURN @String
END
GO
然后叫它:
SELECT dbo.replacement ('A B-C/d')
输出:
A B~C~d