[英]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:創建用戶定義的表類型。 我創建了一個名為“ 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.