SQL Server: update to match and replace only exact

2019-03-03 12:19发布

问题:

I want to match an exact word and replace it with another word.

Here is the SQL Server query that I am using:

UPDATE BODYCONTENT 
SET BODY = CAST(REPLACE(CAST(BODY AS NVARCHAR(MAX)), 'Test' , 'prod') AS NTEXT) 
WHERE BODY COLLATE Latin1_General_CI_AS LIKE '%Test%' COLLATE Latin1_General_CI_AS;

What this query is doing:

'Test','test','TEST' is updated into 'prod' -- This is expected.

'Test2','TestTest', 'Fastest' is updated into 'prod' - I want to avoid this behavior.

Please help.

Other queries I tried but didn't work:

UPDATE BODYCONTENT 
SET BODY = CAST(REPLACE(CAST(BODY AS NVARCHAR(MAX)), 'Test' , 'prod') AS NTEXT) 
WHERE BODY COLLATE Latin1_General_CI_AS LIKE '%[^A-Za-z0-9]Test[^A-Za-z0-9]%' COLLATE Latin1_General_CI_AS;

And when I do a select for 'Test' using the below query:

SELECT * 
FROM dbo.BODYCONTENT 
WHERE CONVERT(NVARCHAR(MAX), BODY) = N'Test';

It is not returning anything. But I could get results using the below queries:

  SELECT BODY 
  FROM dbo.BODYCONTENT 
  WHERE BODY LIKE '%Test%';

  SELECT BODY 
  FROM dbo.BODYCONTENT 
  WHERE BODY COLLATE Latin1_General_CI_AS like '%TEST%' COLLATE Latin1_General_CI_AS;

Here is the column value:

Test testtest Test1 Test TEST

Expected result:

prod testtest Test1 prod prod

Current result:

prod prodprod prod1 prod prod

回答1:

I am getting the impression that all the different versions of test are within the same row value, which is why you are stating that the suggested like 'test' is not working.

Based on this, the below is rather ugly but functional per your requirements:

declare @t table(s ntext);
insert into @t values('Test testtest Test1 Test TEST');

select s as Original
        ,ltrim(rtrim(replace(
                            replace(
                                    replace(N' ' + cast(s as nvarchar(max)) + N' '  -- Add a single space before and after value,
                                            ,' ','<>'                               -- then replace all spaces with any two characters.
                                            )
                                    ,'>test<','>prod<'      -- Use these two characters to identify single instances of 'test'
                                    )
                            ,'<>',' '       -- Then replace the delimiting characters with spaces and trim the value.
                            )
                    )
            ) as Updated
from @t;

Output:

+-------------------------------+-------------------------------+
|           Original            |            Updated            |
+-------------------------------+-------------------------------+
| Test testtest Test1 Test TEST | prod testtest Test1 prod prod |
+-------------------------------+-------------------------------+

The use of <> in place of spaces is due to SQL Server's default behaviour to ignore trailing spaces in string comparisons. These can be any two characters, but I find these to be aesthetically pleasing.