Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MS SQL Server > регулярные выражения в MSSQL T-SQL


Автор: skyboy 4.12.2007, 13:48
Понадобились мне регулярные выражения. После http://dev.mysql.com/doc/refman/5.0/en/regexp.html, ожидал нечто подобное и в таком монстре, как MSSQL Server. А оказалось - нету такого. В поисках downloadable UDF-библиотеки наткнулся на http://www.sqlteam.com/article/regular-expressions-in-t-sql, где описано создание функции для работы с регулярными выражениями при помощи использования объекта VBScript.Regexp. Ну, да, я забыл, что T-SQL может ссылаться не только на библиотеки dll, но и на ActiveX-объекты. Все же, кроссплатформенность даже не предполагается.
Таким образом, функция выглядить следующим образом:
Код

CREATE FUNCTION dbo.regexp_match
    (
        @source varchar(5000),
        @regexp varchar(1000),
        @ignorecase bit = 0
    )
RETURNS bit
AS
    BEGIN
        DECLARE @hr integer
        DECLARE @objRegExp integer
        DECLARE @objMatches integer
        DECLARE @objMatch integer
        DECLARE @count integer
        DECLARE @results bit
        
        EXEC @hr = sp_OACreate 'VBScript.RegExp', @objRegExp OUTPUT
        IF @hr <> 0 BEGIN
            SET @results = 0
            RETURN @results
        END
        EXEC @hr = sp_OASetProperty @objRegExp, 'Pattern', @regexp
        IF @hr <> 0 BEGIN
            SET @results = 0
            RETURN @results
        END
        EXEC @hr = sp_OASetProperty @objRegExp, 'Global', false
        IF @hr <> 0 BEGIN
            SET @results = 0
            RETURN @results
        END
        EXEC @hr = sp_OASetProperty @objRegExp, 'IgnoreCase', @ignorecase
        IF @hr <> 0 BEGIN
            SET @results = 0
            RETURN @results
        END    
        EXEC @hr = sp_OAMethod @objRegExp, 'Test', @results OUTPUT, @source
        IF @hr <> 0 BEGIN
            SET @results = 0
            RETURN @results
        END
        EXEC @hr = sp_OADestroy @objRegExp
        IF @hr <> 0 BEGIN
            SET @results = 0
            RETURN @results
        END
    RETURN @results
    END

А использовать её можно так:
Код

SELECT TOP 5 * FROM "myTable" WHERE dbo.regexp_match("myField",'\d{2,3}$',1) = 1

Подробнее об особенностях VBScript.RegExp лучше http://www.regular-expressions.info/vbscript.html заранее, чтоб не попасть впросак - некоторые отличия от других(к примеру, POSIX) реализаций имеются.

Автор: setnull 10.12.2007, 22:41
А можно уточнить?
Если поле myField проиндексировано, данный запрос воспользуется этим индексом?

Автор: skyboy 10.12.2007, 22:59
Цитата(setnull @  10.12.2007,  21:41 Найти цитируемый пост)
Если поле myField проиндексировано, данный запрос воспользуется этим индексом? 

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

Добавлено через 15 секунд
Цитата(skyboy @  10.12.2007,  21:59 Найти цитируемый пост)
нет

в смысле - не воспользуется

Автор: setnull 11.12.2007, 19:54
Так если рассматривать не структуру индекса, а алгоритм поиска....

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

Автор: skyboy 11.12.2007, 20:43
Цитата(setnull @  11.12.2007,  18:54 Найти цитируемый пост)
Из страницы индексов отобрать строки

так как регулярные выражения - очень гибкий механизм, то подобная страница индексов строилась бы по совпадению/несовпадению с регулярным выражением(так как регулярное выражение может быть и "\d\d", и "^\s.*$"). т.о. сначала строились бы индексы, а потом единократно их использовали бы. смысЛ? я лично не вижу.
единственный смысл был бы при использовании в секции on для join'ов, чтоб несколько раз не вычислять заново значение для незменного аргумента, но, как я понял, детерминистические функции(вызовы с определнными аргументами) и так кешируются, так что в этом отношении все продуманно.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)