Заменить подстроку между двумя разделителями или до конца строки - PullRequest
0 голосов
/ 13 ноября 2018

В процедуре в SQL Server 2008 мне нужно заменить подстроку между 2 идентификаторами.Я не знаю полных строк, подлежащих замене, или если существует второй идентификатор.

Если идентификатор terminator отсутствует, мне нужно, чтобы конец строки считался единым.,Кроме того, идентификаторы могут быть одинаковыми.

DECLARE @startIdenfier VARCHAR(10) = 'the'
DECLARE @endIdenfier   VARCHAR(10) = 'the'
DECLARE @newString     VARCHAR(20) = 'new string that'

Пример ввода / вывода:

'Это старая строка, которая процесс должен применяться. '->
'Это новая строка, к которой процесс необходимо применить.'

'Это старая строка '->
' Это новая строка, которая '

SET @endIdenfier = 'I'

' This старая строка, которая I не нравится '->
' Это новая строка, которая Мне не нравится ''

Это общая замена, и я не смог найти правильный способ сделать это, так как функция REPLACE не принимаетindexes.

РЕДАКТИРОВАТЬ: Это сообщество потрясающе.Извините, я не могу выбрать несколько принятых решений, но я благодарю вас всех за помощь.Я опробую все решения, уже опубликованные (кроме уже принятого, которое я тестировал), и проголосую индивидуально.

Ответы [ 5 ]

0 голосов
/ 13 ноября 2018

Просто используйте STUFF и CHARINDEX. Выяснить:

  • позиция, с которой начинается замена (позиция the + длина the)
  • позиция, в которой заканчивается замена (позиция the начиная с см. Выше)

И вычтите позиции, чтобы вычислить количество заменяемых символов.

DECLARE @string VARCHAR(100) = 'This is the old string that the process needs to be applied on.'
DECLARE @replace VARCHAR(100) = 'NEW STRING THAT '
DECLARE @delim1 VARCHAR(100) = 'the '
DECLARE @delim2 VARCHAR(100) = 'the '

DECLARE @pos1 INT = CHARINDEX(@delim1, @string) + DATALENGTH(@delim1)
DECLARE @pos2 INT = ISNULL(NULLIF(CHARINDEX(@delim2, @string, @pos1), 0), DATALENGTH(@string) + 1)

SELECT STUFF(@string, @pos1, @pos2 - @pos1, @replace)

-- "This is the NEW STRING THAT the process needs to be applied on."

SET @delim2 = 'xxx'
SET @pos1 = CHARINDEX(@delim1, @string) + DATALENGTH(@delim1)
SET @pos2 = ISNULL(NULLIF(CHARINDEX(@delim2, @string, @pos1), 0), DATALENGTH(@string) + 1)

SELECT STUFF(@string, @pos1, @pos2 - @pos1, @replace)

-- "This is the NEW STRING THAT "

Примечание: пробелы должны быть частью разделителей поиска, а не логики. the не должно совпадать them and threfore.

0 голосов
/ 13 ноября 2018

Я думаю, вам нужно будет включить функцию PATINDEX и создать шаблон, используя ваши начальные и конечные идентификаторы. Это будет удовлетворять условию, когда присутствуют как начальный, так и конечный идентификаторы ...

DECLARE @OldString nvarchar(max)
DECLARE @NewString nvarchar(max)
DECLARE @StartLocation bigint
DECLARE @Pattern nvarchar(200) = '%' + @StartIdentifier + ' % ' + @EndIdentifer + '%'
SELECT @StartLocation = PATINDEX(@Pattern, 'old complete string')

Если шаблон расположен, то вы можете получить заменяемую строку путем подстроки «старой полной строки», начиная с позиции (@StartLocation + Length of @StartIdentifier + 1). Чтобы определить длину для SUBSTRING, вам нужно найти позицию @EndIdentifier, используя CHARINDEX старой полной строки, начинающейся с (@StartLocation + Length of @StartIdentifier + 1). Вычтите (@StartLocation + длина StartIdentifier + 1) из результата CHARINDEX.

SELECT @OldString = SUBSTRING('complete old string', @StartLocation + LEN(@StartIdentifier) + 1, CHARINDEX(' ' + @EndIdentifier, 'old complete string', @StartLocation + LEN(@StartIdentifier) + 1) - (@StartLocation + LEN(@StartIdentifier) + 1)))

Вы можете сделать прямую замену, чтобы получить новую строку.

SELECT @NewCompleteString = REPLACE('old complete string', @OldString, @NewString)

"Если нет идентификатора терминатора, мне нужен конец строка, которая будет считаться одной. "

Если исходный шаблон не был найден, мы возвращаемся к поиску только @StartIdentifier. Для этого вы можете сбросить шаблон, чтобы он содержал только @StartIdentifier ...

SELECT @Pattern = '%' + @StartIdentifier + ' %'
SELECT @StartLocation = PATINDEX(@Pattern, 'old complete string')

Если шаблон расположен, вы можете заменить старую строку на SUBSTRING, начиная с (@StartLocation + Length of @StartIdentifier + 1), с длиной длины 'старой полной строки' - (@StartLocation + Length of @StartIdentifier + 1) ...

SELECT @OldString = SUBSTRING('old complete string', @StartLocation + LEN(@StartIdentifier) + 1, LEN('old complete string') - (@StartLocation + LEN(@StartIdentifier) + 1))

Затем вы можете заменить ...

SELECT @NewCompleteString = REPLACE('old complete string', @OldString, @NewString)
0 голосов
/ 13 ноября 2018

Вы можете сделать что-то вроде этого:

/*Declare necessary variables*/
DECLARE @startIndex INT
DECLARE @endIndex INT
DECLARE @startReplace INT
DECLARE @lengthReplace INT
DECLARE @replaceString VARCHAR(500)

/*Get the index of the start/end idenfier*/
SELECT @startIndex = CHARINDEX ( @startIdenfier ,  @originalString)
SELECT @endIndex = CHARINDEX ( @startIdenfier ,  @originalString, @startIndex+1)  

/*In case the end idenfier doesn't exist*/
IF @endIndex = 0
    SET @endIndex = LEN(@originalString) + 1

SET @startReplace = @startIndex + len(@startIdenfier)
SET @lengthReplace = @endIndex - @startReplace

SELECT STUFF(@originalString, @startReplace, @lengthReplace, @newString)
0 голосов
/ 13 ноября 2018
--Find the start index plus the length of the string found (plus one for the space)
SET @startIdx = CHARINDEX(@startIdentifier, @initialString, 1) + LEN(@startIdentifier) + 1

--Find the next occurrence of the end identifier (minus one for the space)
SET @endIdx = CHARINDEX(@endIdentifier, @initialString, @startIdx) - 1;

--end not found?
IF @endIdx = -1 SET @endIdx = LEN(@initialString) + 1;

--Use the STUFF function to remove the old chars from endindex-startindex, and insert the new string at the startindex
SET @results = STUFF(@initialString,  @startIdx, @endIdx - @startIdx, @newString)

В полном объеме:

DECLARE @startIdenfier Varchar(10)
SET @startIdenfier = 'the'
DECLARE @endIdenfier Varchar(10)
SET @endIdenfier = 'the'
DECLARE @newString Varchar(100)
SET @newString = 'new string that'

DECLARE @initialString VARCHAR(256) = 'this is the old string that the process needs to be applied on';

DECLARE @startIdx INT;
SET @startIdx = CHARINDEX(@startIdenfier, @initialString, 1) + LEN(@startIdenfier) + 1;

DECLARE @endIdx INT;
SET @endIdx= CHARINDEX(@endIdenfier, @initialString, @startIdx) - 1;
IF @endIdx = -1 SET @endIdx = LEN(@initialString) + 1;

DECLARE @results VARCHAR(256);
SET @results = STUFF(@initialString,  @startIdx, @endIdx - @startIdx, @newString);

SELECT @results
0 голосов
/ 13 ноября 2018

Примерно так ...

DECLARE @initialString   VARCHAR(32) = '1234567890123456789'
DECLARE @startIdentifier VARCHAR(32) = '34'
DECLARE @endIdentifier   VARCHAR(32) = '34'
DECLARE @newString       VARCHAR(32) = 'ABC'


DECLARE @headChars INT = CHARINDEX(@startIdentifier, @initialString, 1)

IF @headChars > 0
  SET @headChars = @headChars + LEN(@startIdentifier) - 1


DECLARE @bodyChars INT = CHARINDEX(@endIdentifier, @initialString, @headChars + 1)

IF @bodyChars > 0
  SET @bodyChars = LEN(@initialString) - @bodyChars + 1


SELECT
  LEFT(@initialString,  @headChars)
  + @newString
  + RIGHT(@initialString, @bodyChars)

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=b8a179d0e63840dfa60905d9951e4b22

Например ...

'1234567890123456789'
  '34'                => Start @ 1 => Found @  3 => keep chars 1->4
            '34'      => Start @ 5 => Found @ 13 => keep chars 13->end
...