我在List<T>
中有一个名称/值对,需要找到将这些传递给存储过程的最佳方法。
Id Name
1 abc
2 bbc
3 cnn
....
...
实现这一目标的最佳方法是什么?
答案 0 :(得分:2)
在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 :(得分:1)
看看Arrays and Lists in SQL Server 2008以获得一些想法
SQL Server 2008还支持此多行值语法
create table #bla (id int, somename varchar(50))
insert #bla values(1,'test1'),(2,'Test2')
select * from #bla
答案 2 :(得分:0)
我最终使用foreach <insert>
答案 3 :(得分:0)
这可以通过三种方式完成。
我尝试了第一个选项,并在“用户定义的表类型”中传递了成对列表。这对我有用。我在这里发布,可能会对其他人有所帮助。
对我来说,第一个挑战是传递键值对数据结构的列表,第二个遍历列表并将记录插入表中。
步骤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
第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;