Замена только n-го экземпляра символа - PullRequest
6 голосов
/ 13 января 2012

Есть ли способ, которым можно заменить 1-й экземпляр символа в строке чем-то, например.

^1402 WSN NIAMLAB^teertS htimS 005

будет

&1402 WSN NIAMLAB^teertS htimS 005

удерживая второй ^ на месте

Ответы [ 3 ]

21 голосов
/ 13 января 2012

Для замены первого экземпляра символа я бы порекомендовал использовать функции STUFF и CHARINDEX. STUFF вставляет строку в другую строку. Он удаляет указанную длину символов в первой строке в начальной позиции, а затем вставляет вторую строку в первую строку в начальной позиции.

DECLARE @str varchar(100) = '^1402 WSN NIAMLAB^teertS htimS 005'
SELECT STUFF(@str, CHARINDEX('^', @str), 1, '&')

Обратите внимание, что вы также можете использовать STUFF в запросе следующим образом:

SELECT STUFF(<yourcolumn>, CHARINDEX('^', <yourcolumn>), 1, '&')
FROM <yourtable>
2 голосов
/ 13 января 2012

Хотя пример в вашем вопросе состоит в том, как заменить только 1-е вхождение символа, ваш заголовок указывает, что вы хотите заменить n-ное вхождение, что немного сложнее.

Я недавно написал функцию, чтобы найти n-ное вхождение символа в строку.Вы можете использовать, чем построить строку с SUBSTRING.

if exists (
    select 1
    from dbo.sysobjects 
    where id = object_id(N'[dbo].[CHARINDEX3]') 
        and xtype in (N'FN', N'IF', N'TF'))
begin
    drop function [dbo].[CHARINDEX3]
end

GO

/*
Example:
SELECT dbo.CHARINDEX3('a', 'abb abb a', 3)
SELECT dbo.CHARINDEX3('b', 'abb abb a', 5)
SELECT dbo.CHARINDEX3('a', 'abbabba', 3)
SELECT dbo.CHARINDEX3('b', 'abbabba', 5)
If @occurance > the max Occurrence, the function will return the max Occurrence
*/

CREATE FUNCTION dbo.CHARINDEX3
(
    @TargetStr char(1), 
    @SearchedStr varchar(max), 
    @Occurrence int
)
RETURNS INT
AS
BEGIN
    DECLARE @ret INT

    ; WITH
      -- Tally table Gen            Tally Rows:     X2                X3
      t1 AS (SELECT 1 N UNION ALL SELECT 1 N),    -- 4            ,    8
      t2 AS (SELECT 1 N FROM t1 x, t1 y),            -- 16            ,    64
      t3 AS (SELECT 1 N FROM t2 x, t2 y),            -- 256            ,    4096
      t4 AS (SELECT 1 N FROM t3 x, t3 y),            -- 65536        ,    16,777,216
      t5 AS (SELECT 1 N FROM t4 x, t4 y),            -- 4,294,967,296,    A lot
      Numbers AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) Num
                  FROM t3 x, t3 y)
    SELECT TOP 1 @ret = Num 
    FROM
    (
        SELECT Ident = ROW_NUMBER() OVER (ORDER BY N.Num), N.Num 
        FROM Numbers N
        WHERE N.Num <= DATALENGTH(@SearchedStr)
            AND SUBSTRING(@SearchedStr, N.Num, DATALENGTH(@TargetStr)) = @TargetStr
    ) R 
    WHERE Ident <= @Occurrence
    ORDER BY Ident DESC

    RETURN @ret
END

GO

Используя эту функцию, вы можете получить местоположение n-го вхождения и просто вытянуть все символы до и после вхождения, заменив определенное значение.

--Actual Code
DECLARE @loc INT
DECLARE @MyStr VARCHAR(200)
DECLARE @replacement CHAR(1)

SET @MySTr = '^1402 WSN NIAMLAB^teertS htimS 005'
SET @replacement = '$'
SELECT @loc = dbo.CHARINDEX3('^',@MyStr, 2)

SELECT SUBSTRING(@myStr, 1, @loc-1) + @replacement + SUBSTRING(@MyStr, @loc + 1, LEN(@MyStr)-@loc)

Этот пример заменяет только 2-й ^ на $

0 голосов
/ 13 января 2012

Непроверенный код:

SELECT STUFF('^1402 WSN NIAMLAB^teertS htimS 005', charindex('^', '^1402 WSN NIAMLAB^teertS htimS 005'), 1, '&');
GO

Однако, если символ не существует, вы можете заключить его в if / then при charindex('^', '^1402 WSN NIAMLAB^teertS htimS 005') != 0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...