Удалить подстроку между двумя символами в столбце SQL

Допустим, у меня есть таблица T со столбцом S.

Код С 1 \Строка\ Строка 2 Лазер \Лазер\ 3 La\ser\s и \S\trings

Я хочу удалить каждую подстроку в каждой строке TS, которая находится между \ и \, и заменить ее ничем, чтобы таблица T стала

Код С 1 нить 2 Лазер 3 Лас и струны

Я понял, как идентифицировать символы между первым экземпляром \ и \

IF OBJECT_ID(N'tempdb..#t') IS NOT NULL
BEGIN -- Checking to ensure temp table does not exist, and dropping anyone that does to avoid errors

    DROP TABLE #t;
END;

GO

--- Create Temp Table to store values and manipulate before inserting into production table ----

CREATE TABLE #t
(
Code VARCHAR(MAX)
,S VARCHAR(MAX)
);

INSERT INTO #t (Code ,S )
VALUES ('1','\String\ String'),
        ('2','Laser \Laser\'),
        ('3', 'La\ser\s and \S\trings')
SELECT *
FROM   #t;


SELECT REPLACE(REPLACE(SUBSTRING(s, start_pos,  end_pos - start_pos  
    +1), '\', '\'), '\', '\')

FROM   (SELECT s,
               CHARINDEX('\', s) AS start_pos, 
               CHARINDEX('\', s, CHARINDEX('\', s) + 1) AS end_pos
        FROM   #t) t 

Это возвращает

С \Нить\ \Лазер\ \сер\

Я застрял на

  1. Как мне заставить его применяться ко всем экземплярам \\ в одной и той же строке индивидуально (см. строку 3)

  2. Примените это изменение к столбцу в обновлении (я думаю, здесь может быть полезно перекрестное применение)

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
4
0
148
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если бы это был SQL Server 2022 (или более поздняя версия), мы могли бы:

  1. Используйте STRING_SPLIT(,,1), чтобы разбить строку на разделители \ и присвоить каждой части значение ordinal.
  2. Отфильтруйте четные подстроки (оставив нечетные).
  3. Соберите оставшиеся части, используя STRING_AGG().
  4. Добавьте TRIM(), чтобы очистить начальные или конечные пробелы.

Что-то вроде:

SELECT
    T.Code,
    TRIM(STRING_AGG(SS.value, '') WITHIN GROUP(ORDER BY SS.ordinal)) AS Answer
FROM #t T
CROSS APPLY STRING_SPLIT(T.S, '\', 1) SS
WHERE SS.ordinal % 2 != 0 -- Keep the odd parts
GROUP BY T.Code

Третий параметр STRING_SPLIT() генерирует ordinal вдоль каждой value (доступно в SQL Server 2022 и более поздних версиях). На это есть ссылка в предложении WITHIN GROUP(...) функции STRING_AGG(), чтобы гарантировать правильный порядок или повторную сборку компонентов.

Если это часть более сложного запроса, вы можете инкапсулировать логику в CROSS APPLY, на результат которого затем можно будет ссылаться в другом месте.

SELECT
    T.Code,
    CA.Answer
FROM #t T
CROSS APPLY (
    SELECT TRIM(STRING_AGG(SS.value, '') WITHIN GROUP(ORDER BY SS.ordinal)) AS Answer
    FROM STRING_SPLIT(T.S, '\', 1) SS
    WHERE SS.ordinal % 2 != 0 -- Keep the odd parts
) CA
ORDER BY T.Code

В SQL Server 2019 функция STRING_SPLIT() не поддерживает опцию enable_ordinal, поэтому эту функцию нельзя использовать, когда нам нужно гарантировать порядок. Альтернативой является использование метода, который сначала отображает строку в массив JSON, а затем использует OPENJSON() для анализа этого массива.

SELECT
    T.Code,
    CA.Answer
FROM #t T
CROSS APPLY (
    SELECT TRIM(STRING_AGG(SS.value, '') WITHIN GROUP(ORDER BY SS.ordinal)) AS Answer
    FROM (
        SELECT J.value, CONVERT(int, [key]) + 1 AS ordinal
        FROM OPENJSON(CONCAT('["', REPLACE(STRING_ESCAPE(T.S, 'json'), '\\', '","'), '"]')) J
    ) SS
    WHERE SS.ordinal % 2 != 0 -- Keep the odd parts
) CA
ORDER BY T.Code

Приведенное выше преобразует исходную строку в массив JSON, который затем анализируется на отдельные элементы с помощью OPENJSON(). Функция STRING_ESCAPE() защищает JSON от определенных специальных символов (особенно от любых встроенных двойных кавычек), которые в противном случае могли бы вызвать ошибку. Значение key, возвращаемое OPENJSON() выше, представляет собой строку с отсчетом от нуля, которую необходимо преобразовать в целое число и сместить на 1, чтобы она соответствовала STRING_SPLIT()ordinal.

ПРИМЕЧАНИЕ. Существует несколько STRING_SPLIT() альтернатив, но немногие из них дают надежную ordinal ценность. (На самом деле существует несколько плохих ответов, в которых используется логика нумерации после разделения, которая, кажется, работает, но результаты которой не гарантируются какой-либо документированной функцией и которая может сломаться в любой момент - особенно при масштабировании.)

Результаты одинаковы для каждого из вышеперечисленных:

Код Отвечать 1 Нить 2 Лазер 3 Лас и струны

См. эту db<>fiddle для демонстрации.

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

UPDATE T
SET S = CA.Answer
FROM #t T
CROSS APPLY (
    SELECT TRIM(STRING_AGG(SS.value, '') WITHIN GROUP(ORDER BY SS.ordinal)) AS Answer
    FROM (
        SELECT J.value, CONVERT(int, [key]) + 1 AS ordinal
        FROM OPENJSON(CONCAT('["', REPLACE(STRING_ESCAPE(T.S, 'json'), '\\', '","'), '"]')) J
    ) SS
    WHERE SS.ordinal % 2 != 0 -- Keep the odd parts
) CA

Или, если вы предпочитаете включить расчет непосредственно в оператор выбора:

UPDATE T
SET S = (
    SELECT TRIM(STRING_AGG(SS.value, '') WITHIN GROUP(ORDER BY SS.ordinal))
    FROM (
        SELECT J.value, CONVERT(int, [key]) + 1 AS ordinal
        FROM OPENJSON(CONCAT('["', REPLACE(STRING_ESCAPE(T.S, 'json'), '\\', '","'), '"]')) J
    ) SS
    WHERE SS.ordinal % 2 != 0 -- Keep the odd parts
)
FROM #t T

Посмотрите эту обновленную базу данных<>скрипку.

Я получаю сообщение об ошибке «String_Split — недопустимое имя объекта».

Thomas Short 21.05.2024 16:03

@ThomasShort - Увидев тег версии SQL Server в исходном вопросе, я обновил приведенный выше ответ, включив в него версию кода 2019 года. См. раздел выше, начинающийся с «для SQL Server 2019...».

T N 21.05.2024 16:26

Хорошо, спасибо. Я пытаюсь обновить таблицу сейчас ''' UPDATE ST SET S = (SELECT ST2.Code,CA.Answer FROM #t ST2 CROSS APPLY ( SELECT TRIM(STRING_AGG(SS.value, '') Within GROUP(ORDER BY SS. порядковый номер)) AS Ответ FROM ( SELECT J.value, CONVERT(int, [key]) + 1 AS порядковый номер FROM OPENJSON(CONCAT('["', REPLACE(STRING_ESCAPE(ST2.S, 'json'), '\\ ', '","'), '"]')) J ) SS WHERE SS.ordinal % 2 != 0 -- Сохраняем нечетные части ) CA ) FROM dbo.#t ST''' Выдает только ошибку в списке выбора можно указать одно выражение, если подзапрос не введен с помощью EXISTS.

Thomas Short 21.05.2024 16:28

По сути, как мне структурировать это в операторе обновления, чтобы я мог использовать обновленную таблицу в конце моего запроса. Я пробовал использовать внутренние соединения, использовать существует, и я не могу правильно понять синтаксис.

Thomas Short 21.05.2024 16:55

Ответ проще. Поскольку оператор SELECT, опубликованный ранее, уже обращается к таблице и вычисляет ответ, достаточно просто заменить предложение SELECT ... на UPDATE T SET S = CA.Answer. Смотрите мой обновленный ответ выше.

T N 21.05.2024 17:14

См. пример с рекурсивным запросом

with r as (
  select 0 lvl, code,s
    ,case when CHARINDEX('\', s)>0 and  CHARINDEX('\', s, CHARINDEX('\', s) + 1)>0 then
        substring(s,1,CHARINDEX('\', s)-1)
       +substring(s,CHARINDEX('\', s, CHARINDEX('\', s) + 1)+1,len(s)) 
     else s
     end rest
  from #t
  union all
  select r.lvl+1,code,s
    ,case when CHARINDEX('\', rest)>0 
            and  CHARINDEX('\',rest, CHARINDEX('\',rest) + 1)>0 then
        substring(rest,1,CHARINDEX('\', rest)-1)
       +substring(rest,CHARINDEX('\', rest, CHARINDEX('\', rest) + 1)+1,len(s)) 
     else rest
     end rest
  from r where CHARINDEX('\', rest)>0 and CHARINDEX('\',rest, CHARINDEX('\',rest) + 1)>0
)
update #t
  set s=rest
from #t t
left join(
    select * ,max(lvl)over(partition by code) rn
    from r
  )src on src.code= t.code  and src.rn=src.lvl

для тестовых данных

Код С S_upd 1 \Строка\ Строка  Нить 2 Лазер \Лазер\ Лазер 3 La\ser\s и \S\trings Лас и струны 4 Las\ и строка Las\ и строка 5 Лас\ и строка\ Лас 6 Лас и струна\ Лас и струна | 7 \Лас и струна \Лас и струна 8 \Лас и струна\ 9 \L\as и строка\ как и Строка\

Демо

Другие вопросы по теме