Reputation: 1477
I'm using a SQL Server 2014 database and I have a column that contains comma-separated values such as:
1,2,3
4,5
3,6,2
4,2,8
2
What I need to do is to replace the number 2 with the number 3 (string values) in each record and not duplicate the 3 if possible. I'm not sure that this can be done unless I use a function and I'm not sure how to do it in a function.
I think I need to split a string into a table and then loop the values and put it back together with the new value. Is there an easier way? Any help is appreciated.
Expect output would therefore be:
1,3
4,5
3,6
4,3,8
3
Upvotes: 1
Views: 2654
Reputation: 272396
While it is possible, I do not encourage this:
DECLARE @old AS VARCHAR(3) = '2';
DECLARE @new AS VARCHAR(3) = '3';
WITH opdata(csv) AS (
SELECT '1,22,3' UNION ALL
SELECT '1,2,3' UNION ALL
SELECT '4,5' UNION ALL
SELECT '3,6,2' UNION ALL
SELECT '4,2,8' UNION ALL
SELECT '2'
), cte1 AS (
SELECT
csv,
CASE
WHEN ',' + csv + ',' LIKE '%,' + @old + ',%' THEN
CASE
WHEN ',' + csv + ',' LIKE '%,' + @new + ',%' THEN REPLACE(',' + csv + ',', ',' + @old + ',', ',') -- new already present so just delete old
ELSE REPLACE(',' + csv + ',', ',' + @old + ',', ',' + @new + ',') -- replace old with new
END
ELSE ',' + csv + ','
END AS tmp
FROM opdata
)
SELECT
csv,
STUFF(STUFF(tmp, 1, 1, ''), LEN(tmp) - 1, 1, '') AS res
FROM cte1
Result:
csv | res
-------+-------
1,22,3 | 1,22,3
1,2,3 | 1,3
4,5 | 4,5
3,6,2 | 3,6
4,2,8 | 4,3,8
2 | 3
Note that the plethora of ',...,'
is required to avoid replacing values such as 22. If you are using SQL Server 2017 you can ditch the extra CTE + STUFF and use TRIM(',' FROM ...)
.
Upvotes: 3
Reputation: 15997
To update:
DECLARE @was nvarchar(2) = 2,
@willbe nvarchar(2) = 3,
@d nvarchar(1) = ','
UPDATE strings
SET string = REVERSE(
STUFF(
REVERSE(
STUFF(
CASE WHEN CHARINDEX(@d+@willbe+@d,@d+string+@d) > 0
THEN REPLACE(@d+string+@d,@d+@was+@d,@d)
ELSE REPLACE(@d+string+@d,@d+@was+@d,@d+@willbe+@d)
END,1,1,'')
),1,1,''))
Output:
1,3
4,5
3,6
4,3,8
3
Upvotes: 0
Reputation: 1774
May be you are looking something like this.
SELECT REPLACE(CASE WHEN CHARINDEX('2', '1,2,3') > 0 THEN REPLACE('1,2,3', '2','') ELSE REPLACE('1,2,3', '2','3') END, ',,',',')
I have taken a hard coded value for demonstration. You can replace'1,2,3'
with column name in the table.
Upvotes: 1
Reputation: 96016
This isn't going to perform particularly well, however:
WITH CTE AS (
SELECT *
FROM (VALUES ('1,2,3'),
('4,5'),
('3,6,2'),
('4,2,8'),
('2')) V(DS))
SELECT CASE WHEN DS LIKE '%3%' THEN REPLACE(REPLACE(DS,'2,',''),',2','')
WHEN DS LIKE '%2%' THEN REPLACE(DS,'2','3')
ELSE DS
END
FROM CTE;
Upvotes: 1