I am trying to REPLACE multiple characters in SQL Server query and want to achieve this via #temp table instead of nested REPLACE. I got SQL code below and want to achieve result like
ABC
DEF
GHI
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
I can achieve result with nested replace
SELECT REPLACE(REPLACE(REPLACE(t2.STRING_NAME,'_',''),'/',''),' ','') FROM #temp2 t2
but would really like to do this via #temp table. Please can someone help me on this.
When I try to run my first code I get the following error
Msg 512, Level 16, State 1, Line 23 Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= ,
, >= or when the subquery is used as an expression.
SELECT REPLACE(REPLACE(REPLACE(REPLACE('3*[4+5]/{6-8}', '[', '('), ']', ')'), '{', '('), '}', ')'); We can see that the REPLACE function is nested and it is called multiple times to replace the corresponding string as per the defined positional values within the SQL REPLACE function.
Using the REPLACE() function will allow you to change a single character or multiple values within a string, whether working to SELECT or UPDATE data.
In this article, we will see, how to update multiple columns in a single statement in SQL. We can update multiple columns by specifying multiple columns after the SET command in the UPDATE statement. The UPDATE statement is always followed by the SET command, it specifies the column where the update is required.
The REPLACE() function replaces all occurrences of a substring within a string, with a new substring. Note: The search is case-insensitive.
Here is one way using 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 :
result
-----
ABC
DEF
GHI
Note : This will work only if the each string_name
has only one string_to_replace
Update : To handle more than one string_to_replace
in a single string_name
here is one way using Dynamic sql
I have made one small change to the #temp
table by adding a identity
property to loop
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 :
Result
------
ABC
DEF
GHI
ABD
The multiple replace can be achieved via a recursive CTE as per following example:
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
Note that #temp
table was updated to include an extra column called Pattern
, this column contains the search pattern to use in order to find the specific strings that has to be replaced. This was also done to simplify the join statement in the recursive CTE. Also note that in order to find the _
character the search pattern had to be updated as '%[_]%'
. The reason for this is because SQL Server will interpret the _
character as a wild character instead of a specific character we are trying to find.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With