Разделить значение ключа, разделенное двоеточием, в SQL

Я передаю ключевое слово своему SP, скажем, @Keyword. Это ключевое слово может включать

param1:value1 param2:value2

param1:value1 

param2:value2

Как я могу получить значение1 и значение2?


person user960567    schedule 11.05.2015    source источник
comment
Дайте несколько примеров данных, чтобы вам было легко дать точный ответ   -  person Hell Boy    schedule 11.05.2015
comment
Пользовались ли вы поиском на таких сайтах, как name:abc value:good   -  person user960567    schedule 11.05.2015
comment
Итак, вам нужно взять «abc» и «Good» отдельно, верно? Дайте мне пример значения u, передаваемого в @keyword.   -  person Hell Boy    schedule 11.05.2015
comment
Могу я быть плохим парнем и спросить, почему вы хотите сделать это именно так? Используйте параметр с табличным значением.   -  person Bridge    schedule 11.05.2015
comment
@Bridge, мне просто нужно использовать эту функцию везде   -  person user960567    schedule 11.05.2015
comment
Не передавайте составные аргументы такой хранимой процедуре. используйте параметр табличного значения. прочитайте это.   -  person Zohar Peled    schedule 11.05.2015


Ответы (4)



Вы можете использовать .nodes для типа xml и строковых функций, таких как LEFT / CHARINDEX / SUBSTRING, для достижения этой цели.

Запрос

DECLARE @v VARCHAR(MAX) = 'param1:value1 param2:value2'

DECLARE @xml xml = '<x>' + REPLACE(@v,' ','</x><x>') + '</x>'
;WITH CTE AS 
(
SELECT c.value('.','NVARCHAR(MAX)') as val
FROM @xml.nodes('x') t(c)
)
SELECT
LEFT(val,CHARINDEX(':',val)-1),
SUBSTRING(val,CHARINDEX(':',val)+1,LEN(val)-CHARINDEX(':',val))
FROM cte

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

Примечание. В приведенном выше коде предполагается, что пробелы <x>,</x> и ' ' не являются допустимыми параметрами или значениями.

Вот еще один способ,

            ALTER FUNCTION [dbo].[GetValueByKey]
            (
                @Key nvarchar(max)
                ,@Str nvarchar(max)
            )
            RETURNS NVARCHAR(MAX)
            AS
            BEGIN

                DECLARE @Result nvarchar(max) = '';
                DECLARE @KeyIndex int = 0; 
                DECLARE @SpaceIndex int = 0; 

                SELECT @KeyIndex = CHARINDEX(@Key + ':', @Str);

                IF(@KeyIndex > 0)
                BEGIN
                    SET @KeyIndex = @KeyIndex + LEN(@Key) + 1;
                    SET @Result = SUBSTRING(@Str, @KeyIndex, LEN(@Str) - @KeyIndex + 1);
                    SELECT @SpaceIndex = CHARINDEX(' ', @Result);
                    IF(@SpaceIndex <= 1)
                    BEGIN
                        SET @SpaceIndex = LEN(@Result)  +1;
                    END
                    SELECT @Result = SUBSTRING(@Result, 0, @SpaceIndex)
                END

                RETURN @Result;
            END
person ughai    schedule 11.05.2015
comment
Но это может быть что угодно :( - person user960567; 11.05.2015
comment
хорошо, если пространство также разрешено как значение, как будет работать разделение param1:value1 param2:value2? - person ughai; 11.05.2015
comment
Обновил ваш ответ, потому что я тоже нашел способ. - person user960567; 11.05.2015
comment
Поскольку ваш ответ в корне отличается от моего, я бы предложил вам создать новый ответ или, что еще лучше, добавить его в свой вопрос в качестве редактирования и упомянуть, что это то, что вы пробовали до сих пор. - person ughai; 11.05.2015

Как насчет того, чтобы просто указать param1 и param2 в качестве параметров вашей хранимой процедуры?

CREATE PROCEDURE procedurename
    @param1   datatype
  , @param2   datatype
AS
  content here
GO
person Toby    schedule 11.05.2015

Вот еще один способ использования функции разделения. Для справки см. эту статью Джеффа Модена.

По сути, вы хотите разделить @keyword, используя ' ' (пробел) в качестве разделителя. Затем, используя некоторые строковые функции, такие как LEFT, SUBSTRING и CHARINDEX, вы можете извлечь param и его value.

DECLARE @keyword VARCHAR(8000)
SELECT @keyword = 'param1:value1 param2:value2'

;WITH CteSpace AS(
    SELECT *
    FROM dbo.DelimitedSplit8K(@keyword, ' ')
)
SELECT
    Param = LEFT(Item, CHARINDEX(':', Item) - 1),
    Value = SUBSTRING(Item, CHARINDEX(':', Item) +1, LEN(Item) - CHARINDEX(':', Item))
FROM CteSpace
person Felix Pamittan    schedule 11.05.2015

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

CREATE TYPE Keywords AS Table
(
    Keyword_ParamName varchar(10), -- or whatever length that suits your needs
    Keyword_value varchar(200), -- or whatever length that suits your needs
)

Затем просто объявите параметр @keyword как этот тип:

CREATE PROCEDURE stp_doWhatever 
(
    @Keyword dbo.Keywords READONLY -- Note: Readonly is a must!
)
AS
-- do whatever

Вы можете использовать @keyword в качестве таблицы в хранимой процедуре для выполнения операций выбора, объединения и всего, что вам нужно.

person Zohar Peled    schedule 11.05.2015