繁体   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