MSSQL: значение подстроки с использованием внутреннего значения параметра

У меня две переменные. первая переменная @WhereClause содержит значение:   c1 = 'v111' и c2 = 'v222' и c3 = 'v333' и c4 = 'v444' .

вторая переменная @ConditionFields содержит значение: c2, c4 .

Теперь, как я могу получить только значение c2 и c4. значение @NewWhereClause будет: c2 = 'v222' и c4 = 'v444' . пожалуйста помоги.

0
nl ja de
Вы пытаетесь проанализировать строку @WhereClause для значений в них? Если да, то почему?
добавлено автор Gordon Linoff, источник
Если они передаются из внешнего кода, я бы рекомендовал заменить их табличными параметрами. Если они являются внутренними для кода, над которым вы работаете, я бы рекомендовал заменить их на переменные таблицы. В любом случае, я рекомендую попробовать работать со структурированными данными, пытаясь выполнять сложные манипуляции с строками каждый раз.
добавлено автор Damien_The_Unbeliever, источник
что вы подразумеваете под «получить только значение c2 и c4»? Не могли бы вы разместить весь свой запрос.
добавлено автор Scorpion, источник

2 ответы

Это может показаться странным способом сделать это, но оно работает - я уверен, что это также можно оптимизировать, и есть несколько разных способов «Разделить» строки, я просто подумал, что это довольно круто.

DECLARE @WhereClause varchar(MAX)
DECLARE @NewWhereClause varchar(MAX)
DECLARE @ConditionFields varchar(MAX)
DECLARE @Delimiter char(1)
DECLARE @X xml
DECLARE @TempCondition varchar(MAX)
DECLARE @TempWhereClause varchar(MAX)

SET @WhereClause = 'c1=''v111'' and c2=''v222'' and c3=''v333'' and c4=''v444'''
SET @ConditionFields = 'c2,c4'
SET @Delimiter = ','
SET @NewWhereClause = ''

SELECT @X = CONVERT(xml,'' + REPLACE(@ConditionFields,@Delimiter,'') + '')

DECLARE ColCursor CURSOR FOR 
SELECT [Value] = T.c.value('.','varchar(20)')
FROM @X.nodes('/root/s') T(c)
WHERE T.c.value('.','varchar(20)') <> ''

OPEN ColCursor   
FETCH NEXT FROM ColCursor INTO @TempCondition   

WHILE @@FETCH_STATUS = 0   
BEGIN   
    SELECT @TempWhereClause = SUBSTRING(@WhereClause, CHARINDEX(@TempCondition, @WhereClause), CHARINDEX(' ', @WhereClause))
    IF @NewWhereClause = ''
    BEGIN
        SET @NewWhereClause = @TempWhereClause
    END
    ELSE
    BEGIN
        SET @NewWhereClause += ' and ' + @TempWhereClause
    END

    FETCH NEXT FROM ColCursor INTO @TempCondition   
END   

CLOSE ColCursor   
DEALLOCATE ColCursor

SELECT @NewWhereClause

Вот SQL Fiddle :

0
добавлено
Это довольно изящно. Все случаи использования, которые я пробовал, за исключением сценария, в который вы помещаете значение условия, которого нет в WhereClause. Когда я делаю это, он включает в себя первый узел, независимо от того, что я вставляю. Попробуйте «c1, c4, c6, c8», чтобы понять, что я имею в виду. Какие-либо изменения вы можете исправить?
добавлено автор Eric J. Price, источник

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

/*
This will work assuming your variable formats are always consistent with no leading or trailing spaces:
@WhereClause format (SingleValue:"c1='v111'"; MultipleValues:"c1='v111' and c2='v222' and x#='...' and 'c156='anything'"
@ConditionFields format (SingleValue:"c2"; MultipleValues:"c2,c4,c7,...,c156"
*/

Create  Function dbo.ApplyConditionFields (@WhereClause Varchar(Max), @ConditionFields Varchar(Max))
Returns Varchar(Max)
With    Execute As Caller
As
Begin
        Declare @output Varchar(Max)

        If      @WhereClause Like '%=%'
        Begin
                ;With   parsedWhere As
                (
                        Select  Left(@WhereClause,CharIndex('=',@WhereClause)-1) As parsedVar,
                                Substring(@WhereClause,CharIndex('=',@WhereClause)+1,CharIndex(' ',@WhereClause+' ')-CharIndex('=',@WhereClause)-1) As parsedVal,
                                LTrim(Replace(Right(@WhereClause+' and ',Len(@WhereClause+' and ')-CharIndex(' and ',@WhereClause + ' and ')+2),' and ',' ')) As rest
                        Union   All
                        Select  Left(rest,CharIndex('=',rest)-1) As parsedVar,
                                Substring(rest,CharIndex('=',rest)+1,CharIndex(' ',rest)-CharIndex('=',rest)-1) As parsedVal,
                                Right(rest,Len(rest)-CharIndex(' ',rest)+1) As rest
                        From    parsedWhere
                        Where   rest <> ' '
                ),      parsedFields As
                (
                        Select  Left(@ConditionFields+',',CharIndex(',',@ConditionFields + ',')-1) As parsedVar,
                                Right(@ConditionFields+',',Len(@ConditionFields+',')-CharIndex(',',@ConditionFields+',')) As rest
                        Union   All
                        Select  Left(rest,CharIndex(',',rest + ',')-1) As parsedVar,
                                Right(rest,Len(rest)-CharIndex(',',rest+',')) As rest
                        From    parsedFields
                        Where   rest <> ''
                )   
                Select  @output = Coalesce(@output+' and ','')+pw.parsedVar+'='+pw.parsedVal
                From    parsedWhere pw
                Join    parsedFields pf
                        On  pw.parsedVar = pf.parsedVar
        End

        Return(@output)
End
0
добавлено
SqlCom.ru - Стиль жизни SQL
SqlCom.ru - Стиль жизни SQL
908 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только MS SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz). Предложения в @sql_ninja

SQL_Ninja
SQL_Ninja
340 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz)