SQL Server заменяет все значения перед двоеточием и после точки с запятой - PullRequest
1 голос
/ 13 марта 2012

У меня есть столбец сказать Test.

Тест имеет значения как asp:test;abca, asps:tesst;abcsa, asssp:tsest;assbca

Меня интересует только текст до ; и после :, поэтому мой результат должен быть как

test, tesst, tsest

Я просто хочу сделать это с помощью SQL-запроса, а не программно в коде.

Поддерживает ли SQL Server какое-либо регулярное выражение?

Любая помощь приветствуется.

EDIT

Самая важная часть состоит в том, что некоторые значения могут не иметь ; и :, поэтому мой запрос также не должен завершиться с ошибкой, может быть своего рода проверка для этого

Ответы [ 7 ]

5 голосов
/ 13 марта 2012
declare @T table
(
  Col varchar(20)
)

insert into @T values
('asp:test;abca'), 
('asps:tesst;abcsa'), 
('asssp:tsest;assbca'),
('asssp:tsestassbca'),
('asssptsest;assbca'),
('asssptsestassbca'),
(':;')

select  left(T2.Col, charindex(';', T2.Col+';')-1) 
from @T as T1
  cross apply (select stuff(T1.Col, 1, charindex(':', T1.Col), '')) as T2(Col)
4 голосов
/ 13 марта 2012

Для строковых функций, поддерживаемых движком sql: substring, charindex:

SUBSTRING(s, CHARINDEX(':', s) + 1, CHARINDEX(';', s) - CHARINDEX(':', s) - 1)

Полный код с обработкой ошибок

case 
  when CHARINDEX(':', s) > 0 and CHARINDEX(';', s) > 0 
    then SUBSTRING(s, CHARINDEX(':', s) + 1, CHARINDEX(';', s) - CHARINDEX(':', s) - 1) 
 else null
end
3 голосов
/ 13 марта 2012

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

Declare @Temp Table(Test VarChar(50))

Insert Into @Temp Values('asp:test;abca')
Insert Into @Temp Values('asps:tesst;abcsa')
Insert Into @Temp Values('asssp:tsest;assbca')
Insert Into @Temp Values('Hello World')
Insert Into @Temp Values('Hello World:')
Insert Into @Temp Values('Hello World;')

Select  SubString(Test, CharIndex(':', Test) + 1, CharIndex(';', Test + ':;') - CharIndex(':', Test) - 1)
From    @Temp
3 голосов
/ 13 марта 2012

T-SQL имеет PATINDEX для сопоставления с образцом, но не поддерживает надежный API регулярных выражений. Однако если у вас SQL Server 2005 и более поздние версии, вы можете создать пользовательскую функцию CLR . Тем не менее, вы можете достичь желаемого с помощью обычной пользовательской функции, используя PATINDEX / CHARINDEX и SUBSTRING.

2 голосов
/ 13 марта 2012

Вы можете написать такую ​​функцию, которая будет обрабатывать все случаи - есть двоеточие (:) и / или точка с запятой (;) - или вообще нет. В любом случае это вернет искомый фрагмент строки:

ALTER FUNCTION dbo.ExtractString (@InputString VARCHAR(500))
RETURNS VARCHAR(500)
AS BEGIN
    DECLARE @Result VARCHAR(500)

    DECLARE @ColonPos INT, @SemicolonPos INT

    SET @ColonPos = CHARINDEX(':', @InputString)
    SET @SemicolonPos = CHARINDEX(';', @InputString)

    IF @ColonPos > 0 
        IF @SemicolonPos > 0
            SET @Result = SUBSTRING(@InputString, @ColonPos + 1, @SemicolonPos - 1 - @ColonPos)
        ELSE    
            SET @Result = SUBSTRING(@InputString, @ColonPos + 1, 500)
    ELSE
        IF @SemicolonPos > 0
            SET @Result = SUBSTRING(@InputString, 1, @SemicolonPos - 1)
        ELSE    
            SET @Result = @InputString

    RETURN @Result
END

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

Если вы запускаете его для разных входов:

SELECT 
    dbo.ExtractString('asp:test;abca'),
    dbo.ExtractString('asps:tesst;abcsa'), 
    dbo.ExtractString('asssp:tsest;assbca'),
    dbo.ExtractString('test'),
    dbo.ExtractString('a:test'),
    dbo.ExtractString('atest;something')

вы получите эти результаты:

test   tesst   tsest   test   test   atest
1 голос
/ 13 марта 2012

Что-то в этом роде?

DECLARE @n TABLE (test VARCHAR(100))

INSERT @n (test)
VALUES  ('asp:test;abca'), ('asps:tesst;abcsa'), ('asssp:tsest;assbca')

INSERT @n (test)
VALUES  ('asptest;abca'), ('asps:tesstabcsa'), ('asssptsestassbca')


SELECT SUBSTRING(test, CHARINDEX(':', test) + 1, ISNULL(NULLIF(CHARINDEX(';', test), 0), LEN(test) + 1) - CHARINDEX(':', test) - 1)
FROM @n
0 голосов
/ 13 марта 2012

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

Однако вы должны знать, что использование этих методов как части предложения WHERE, вероятно, приведет к сканированию таблицы.

В зависимости от размера ваших данных, нагрузки на сервер и частоты выполнения этого запроса может иметь смысл попробовать что-то еще.Например, добавление еще одного столбца с заполненными этими данными.

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