Извлечение из текста с помощью tsql

У меня есть следующий формат строки в столбце таблицы Sql

[CID]: 267 [MID]: 319A [Name]: RJR

Как я могу извлечь только значение MID, которое составляет 319A в запросе на выборку, чтобы я мог использовать MID в соединении. Другими словами, мне нужно извлечь значение MID из этого текстового поля, чтобы использовать его в объединении. Я копирую/вставляю значение, и похоже, что после каждого значения есть символы /n (новая строка).

заранее спасибо


person Sev    schedule 24.02.2012    source источник
comment
Я думаю, вам нужно создать хранимую функцию, которая получает строку в качестве параметра и возвращает значение MID в качестве результата.   -  person teran    schedule 25.02.2012
comment
другие строки такие же, но с другими значениями. 319A может быть DS324A или 32456A или 31   -  person Sev    schedule 25.02.2012
comment
Строковые функции SQL слабы. И если MID или NAME отсутствуют, он может отправить недопустимый номер в подстроку, и ваш запрос завершится ошибкой (например, ошибка, при которой строки больше не обрабатываются). Я бы подумал о переходе на Regex, как это предложил Xeno.   -  person paparazzo    schedule 25.02.2012
comment
Когда вы сохраняете эти данные в базе данных, почему бы вам не разделить их, а хранить вместе? Очевидно, в этой строке есть некоторые встроенные данные, которые важны сами по себе. Почему вы хотите похоронить его как часть другой строки?   -  person Aaron Bertrand    schedule 25.02.2012
comment
Данные существуют. я не могу это изменить   -  person Sev    schedule 25.02.2012


Ответы (4)


вы можете попробовать этот.

declare 

    @t varchar(100)
    set @t = '[CID]: 267 [MID]: 319A [Name]: RJR';
    select ltrim(rtrim(substring(@t,charindex('[MID]:',@t)+6,(charindex('[NAME]',@t))-(charindex('[MID]:',@t)+6))))
---------------------------------------------------------
319A

ltrim и rtrim урежут ваше значение 319A. вы можете попробовать без них в начале, если хотите.


Ваше здоровье

person Sergey Benner    schedule 24.02.2012
comment
Мне это нравится, но он говорит о недопустимых значениях столбца [MID]: и [Name]: - person Sev; 25.02.2012
comment
мои плохие одинарные кавычки вместо двойных кавычек. я отредактировал ответ - person Sergey Benner; 25.02.2012
comment
да, понял... Я обновил сдвиг индекса для обеих функций charindex. - person Sergey Benner; 25.02.2012
comment
Теперь у меня есть 319A, за которым следует [Имя.... Я должен сказать получить значение перед [Имя - person Sev; 25.02.2012
comment
Все в порядке, я просто тупой. последний параметр подстроки - это размер, который нужно взять, поэтому мы вычитаем индекс [середины] из индекса [имени], и это должен быть ваш размер значения для обрезки. - person Sergey Benner; 25.02.2012
comment
Я получаю следующую ошибку: Недопустимый параметр длины, переданный в функцию LEFT или SUBSTRING. Серьезность 16 Состояние 4 - person Sev; 25.02.2012
comment
просто обновление моего реального [MID]: имеет 12 символов, поэтому я изменил 6 на 12 в своем запросе - person Sev; 25.02.2012
comment
Другими словами, это примерно так: [MyID00022]: - person Sev; 25.02.2012
comment
нет необходимости манипулировать вашей строкой. это фиксированный. просто попробуйте сейчас и поставьте вместо @t свой столбец и добавьте from yourtable конечно - person Sergey Benner; 25.02.2012
comment
select ltrim(rtrim(substring(BatchData,charindex('[MyID00022]:',BatchData)+12, (charindex('[Name0000001]:',BatchData))-(charindex('[MyID00022]:',BatchData)+ 12)))) из моего стола - person Sev; 25.02.2012
comment
Это отображает правильное значение, но затем выдает следующую ошибку: Недопустимый параметр длины, переданный в функцию LEFT или SUBSTRING. Серьезность 16 Состояние 4 - person Sev; 25.02.2012
comment
имейте в виду, что значение 319A может измениться. На 319 или 319304 например - person Sev; 25.02.2012
comment
возможно, у вас есть некоторые строки, которые не соответствуют этому описанию, в котором говорится, что, вероятно, нет тегов [MID] или [NAME] или они присутствуют, но в другом порядке, поэтому это не удается, возможно, вы должны очистить свои строки. это работает наверняка. - person Sergey Benner; 25.02.2012
comment
регулярное выражение требует установки clr. не всем нравится устанавливать лишнее на prod серверах... - person Sergey Benner; 25.02.2012
comment
@SergeyBenner Я согласен, что clr не для всех. Я хотел прокомментировать главное, так как не хотел отвлекать внимание от вашего ответа. +1 - person paparazzo; 25.02.2012
comment
@sev длина чего? тега [MID]: ровно 6 символов ??? если длина ваших тегов изменится, будет сложно определить начальный индекс вашей строки поиска. у вас должны быть некоторые начальные и конечные точки вашей строки поиска, иначе нет хорошего способа определить ее без регулярных выражений - person Sergey Benner; 25.02.2012
comment
Хорошо, я нашел проблему. Проблема в том, что в некоторых моих строках [Имя]: отсутствует, что не является хорошей новостью. Это привело к минусу charindex - person Sev; 25.02.2012
comment
@Sev Смотрите мой комментарий к вашему вопросу. И если MID или NAME отсутствуют, он может отправить недопустимый номер в подстроку, и ваш запрос завершится ошибкой (например, ошибка, при которой строки больше не обрабатываются). - person paparazzo; 25.02.2012

http://www.simple-talk.com/sql/t-sql-programming/tsql-regular-expression-workbench/

добавить поддержку регулярных выражений на сервер sql

Rubular Regex для начала:

\[MID\]: (.*) \[Name]:
person Abdul Hfuda    schedule 24.02.2012

ВООБЩЕ не чисто, но если вам это нужно в SQL, вот вам:

Использовать

SUBSTRING ( value_expression , start_expression , length_expression )

а также

 LOCATE( string1, string2 [, start] ) 

вместе:

SUBSTRING(INPUT, 
         ((SELECT LOCATE( 'MID]: ', INPUT ))+6),
         ((SELECT LOCATE( '[Name]', INPUT )) - ((SELECT LOCATE( 'MID]: ', INPUT ))+6))

смотря где происходит? Если это пакетный процесс, я бы экспортировал эти поля с идентификатором, написал Perl One Liner, который их извлекает, а затем загрузил их обратно в базу данных. это было бы намного быстрее, чем использование этих функций.

если это экранное событие, то я предлагаю вместо этого разбить их на 3 столбца, это действительно сэкономит вам место.

person Isaac    schedule 24.02.2012
comment
что 319A является динамическим значением. это может быть 232394AДобавить - person Sev; 25.02.2012
comment
@Jordan, на каком диалекте используется LOCATE? Я не мог заставить это работать в SQL Server. ('LOCATE' is not a recognized built-in function name.) - person Aaron Bertrand; 25.02.2012
comment
@sev, где в коде это не предусмотрено? +6 потому, что locate возвращает индекс начала строки. - person Isaac; 25.02.2012
comment
@AaronBertrand, попробуйте CHARINDEX (выражение1, выражение2 [, start_location]). Он делает то же самое. - person Isaac; 25.02.2012
comment
Вы должны изменить свой ответ, а не говорить мне в комментарии. - person Aaron Bertrand; 25.02.2012

Не думайте, что вам нужны все эти функции обрезки и подстроки.

USE tempdb;
GO

CREATE TABLE #t1
(
    a INT,
    b VARCHAR(64)
);
INSERT #t1 SELECT 1, '[CID]: 267 [MID]: 319A [Name]: RJR'
UNION ALL  SELECT 2, '[CID]: 26232 [MID]: 229dd5A [Name]: RJ'
UNION ALL  SELECT 3, 'Garbage that will not match';

CREATE TABLE #t2
(
    c INT,
    d VARCHAR(32)
);
INSERT #t2 SELECT 4, '319A'
UNION ALL  SELECT 5, '229dd5A'
UNION ALL  SELECT 6, 'NO MATCH';

SELECT t1.a, t1.b, t2.c, t2.d
  FROM #t1 AS t1 
  INNER JOIN #t2 AS t2
  ON t1.b LIKE '%`[MID`]: ' + t2.d + ' %' ESCAPE '`'

GO
DROP TABLE #t1, #t2;

Если вы понятия не имеете, сколько пробелов может быть между [MID]: и началом вашего значения или концом вашего значения и началом следующего [, и предполагая, что в значениях, которые вы хотите сопоставить, нет пробелов, вы можете использовать :

  ON REPLACE(t1.b, ' ', '') LIKE '%`[MID`]:' + t2.d + '`[%' ESCAPE '`'
person Aaron Bertrand    schedule 24.02.2012