передача списка пар имя / значение в хранимую процедуру - PullRequest
0 голосов
/ 11 августа 2010

У меня есть пара имя / значение в List<T>, и мне нужно найти лучший способ передать их в хранимую процедуру.

Id   Name
1    abc
2    bbc
3    cnn
....
...

Каков наилучший способ сделать это?

Ответы [ 4 ]

2 голосов
/ 11 августа 2010

Один из способов справиться с этим в SQL Server 2005 (до появления табличных параметров) - передать список с разделителями и использовать функцию Split.Если вы используете массив из двух столбцов, вы можете использовать два разных разделителя:

Declare @Values varchar(max)
Set @Values = '1,abc|2,bbc|3,cnn'

With SplitItems As
    (
    Select S.Value As [Key]
        , S2.Value
        , Row_Number() Over ( Partition By S.Position Order By S2.Position ) As ElementNum
    From dbo.Split(@Values,'|') As S
        Outer Apply dbo.Split(S.Value, ',') As S2
    )
Select [Key]
    , Min( Case When S.ElementNum = 1 Then S.Value End ) As ListKey
    , Min( Case When S.ElementNum = 2 Then S.Value End ) As ListValue
From SplitItems As S
Group By [Key]

Create Function [dbo].[Split]
(   
    @DelimitedList nvarchar(max)
    , @Delimiter nvarchar(2) = ','
)
RETURNS TABLE 
AS
RETURN 
    (
    With CorrectedList As
        (
        Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
            + @DelimitedList
            + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
            As List
            , Len(@Delimiter) As DelimiterLen
        )
        , Numbers As 
        (
        Select Row_Number() Over ( Order By c1.object_id ) As Value
        From sys.columns As c1
            Cross Join sys.columns As c2
        )
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
        , Substring (
                    CL.List
                    , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen     
                    , CharIndex(@Delimiter, CL.list, N.Value + 1)                           
                        - ( CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen ) 
                    ) As Value
    From CorrectedList As CL
        Cross Join Numbers As N
    Where N.Value < Len(CL.List)
        And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter
    )

Другой способ справиться с этим без табличных параметров - передать Xml как nvarchar (max):

Declare @Values nvarchar(max)
Set @Values = '<root><Item Key="1" Value="abc"/>
<Item Key="2" Value="bbc"/>
<Item Key="3" Value="cnn"/></root>'

Declare @docHandle int
exec sp_xml_preparedocument @docHandle output, @Values

Select *
From OpenXml(@docHandle, N'/root/Item', 1) 
    With( [Key] int, Value varchar(10) )
1 голос
/ 11 августа 2010

Взгляните на Массивы и списки в SQL Server 2008 , чтобы получить некоторые идеи

SQL Server 2008 также поддерживает синтаксис многострочных значений

create table #bla (id int, somename varchar(50))

insert #bla values(1,'test1'),(2,'Test2')

select * from #bla
0 голосов
/ 22 января 2019

Это можно сделать тремя способами.

  1. Определяемый пользователем тип таблицы
  2. Синтаксический анализ объекта Json
  3. Синтаксический анализ XML

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

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

Шаг 1: Создание пользовательского типа таблицы.Я создал с именем «TypeMetadata».Поскольку это пользовательский тип, я создал два атрибута типа nvarchar.Вы можете создать один из типа integer и второй типа nvarchar.

    -- Type: metadata ---
IF EXISTS(SELECT * FROM SYS.TYPES WHERE NAME = 'TypeMetadata')
    DROP TYPE TypeMetadata
GO
CREATE TYPE TypeMetadata AS TABLE (
    mkey nvarchar (50), 
    mvalue nvarchar (50)
    );
GO

Шаг 2: Затем я создал хранимую процедуру с именем 'createfiled'

    -- Procedure: createtext --
CREATE PROCEDURE [dbo].[createfield] 
    @name nvarchar(50),
    @text nvarchar(50),
    @order int, 
    @type nvarchar(50),
    @column_id int , 
    @tid int,   
    @metadataList TypeMetadata readonly
AS
BEGIN  

--loop through metadata and insert records -- 
DECLARE @mkey nvarchar(max);
DECLARE @mvalue nvarchar(max);

DECLARE mCursor CURSOR LOCAL FAST_FORWARD
FOR
    SELECT mkey, mvalue
        FROM @metadataList;
        OPEN mCursor;

        FETCH NEXT FROM mCursor INTO @mkey, @mvalue; -- Initial fetch attempt

        WHILE @@FETCH_STATUS = 0
        BEGIN
           INSERT INTO template_field_metadata (name, value, template_field_id, isProperty) values (@mkey, @mvalue, 1, 0) 
           PRINT 'A new metadata created with id : ' + cast(SCOPE_IDENTITY() as nvarchar); 
           FETCH NEXT FROM mCursor INTO @mkey, @mvalue;  -- Attempt to fetch next row from cursor
        END;

        CLOSE mCursor;
DEALLOCATE mCursor;

END
GO

Шаг 3: наконец я выполнилхранимая процедура, как;

DECLARE @metadataToInsert TypeMetadata;
INSERT INTO @metadataToInsert VALUES ('value', 'callVariable2');
INSERT INTO @metadataToInsert VALUES ('maxlength', '30');

DECLARE @fid INT;
EXEC [dbo].[createfield] @name = 'prefagent', @text = 'Pref Agent', @order = 1 , @type= 'prefagent', @column_id = 0, @tid = 49, @metadataList =@metadataToInsert;
0 голосов
/ 30 августа 2010

я заканчиваю, используя foreach <insert>

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