簡體   English   中英

將名稱/值對的列表傳遞到存儲過程

[英]passing list of name/value pairs to stored procedure

我在List<T>有一個名稱/值對,需要找到將它們傳遞給存儲過程的最佳方法。

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

做到這一點的最佳方法是什么?

在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) )

查看SQL Server 2008中的數組和列表,以獲取一些想法

SQL Server 2008還支持此多行值語法

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

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

select * from #bla

我最終使用foreach <insert>

這可以通過三種方式完成。

  1. 用戶定義表類型
  2. Json對象解析
  3. XML解析

我嘗試了第一個選項,並在“用戶定義的表類型”中傳遞了對的列表。 這對我有用。 我在這里發布,可能會對其他人有所幫助。

對我來說,第一個挑戰是傳遞鍵值對數據結構的列表,第二個遍歷該列表並將記錄插入表中。

步驟1:創建用戶定義的表類型。 我創建了一個名為“ TypeMetadata”的文件。 由於是自定義類型,因此創建了兩個類型為nvarchar的屬性。 您可以創建整數類型之一,並創建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

第三步:最后我執行了類似的存儲過程;

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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM