我有一个存储过程,其参数名为Id
:
CREATE PROCEDURE [TargetSp](
@Id [bigint]
)
AS
BEGIN
Update [ATable]
SET [AColumn] =
(
Select [ACalculatedValue] From [AnotherTable]
)
Where [ATable].[Member_Id] = @Id
END
所以我需要将它用于Id的列表,而不是像以下那样的Id:
Exec [TargetSp]
@Id IN (Select [M].[Id] From [Member] AS [M] Where [M].[Title] = 'Example');
首先:我如何为列表执行它?
第二:我执行sp多次或在目标脚本中重写它有什么性能差异?
答案 0 :(得分:3)
您可以使用表值参数(请参阅http://msdn.microsoft.com/en-us/library/bb510489.aspx)。通常,如果您只向服务器发送一个请求而不是请求列表,则会看到更短的执行时间。
答案 1 :(得分:1)
我通常会传递像XML这样的信息,然后就可以像使用它一样使用它...根据需要选择,插入,更新
DECLARE @IDS NVARCHAR(MAX), @IDOC INT
SET @IDS = N'<ROOT><ID>1</ID><ID>2<ID></ROOT>'
EXEC sp_xml_preparedocument @IDOC OUTPUT, @IDS
SELECT [ID] FROM OPENXML (@IDOC, '/ROOT/ID', 2) WITH ([ID] INT '.') AS XMLDOC
EXEC sp_xml_removedocument @IDOC
答案 2 :(得分:1)
与freefaller的例子类似,但是改为使用xml类型并插入表变量@ParsedIds
DECLARE @IdXml XML = N'<root><id value="1"/><id value="2"/></root>'
DECLARE @ParsedIds TABLE (parsedId int not null)
INSERT INTO @ParsedIds (parsedId)
SELECT v.parsedId.value('@value', 'int')
FROM @IdXml.nodes('/root/id') as v(parsedId)
SELECT * FROM @ParsedIds
有趣的是,我已经开发了一个拥有1000个用户的大规模系统,我们发现使用这种方法可以为小的id列表(不超过5个id)执行表值参数方法。对于较大的Id列表,表值参数方法更快。
编辑问题后编辑:
查看您的示例,您似乎希望根据Title参数更新ATable。如果除了title参数之外,你可以从重写存储过程中受益。
create procedure [TargetSP](
@title varchar(50)
)
as
begin
update [ATable]
set [AColumn] =
(
select [ACalculatedValue] from [AnotherTable]
)
where [ATable].[Member_Id] in (select [M].[Id] from [Member] as [M] where [M].[Title] = @title);
end
答案 3 :(得分:1)
由于您只关心标题为“Example”的所有行,因此您不需要首先确定列表,然后告诉SQL Server您要更新的列表,因为您已经可以识别具有查询的列表。那么为什么不这样做呢(我在这里猜测一些数据类型):
ALTER PROCEDURE dbo.TargetSP
@title VARCHAR(255)
AS
BEGIN
SET NOCOUNT ON;
-- only do this once instead of as a subquery:
DECLARE @v VARCHAR(255) = (SELECT [ACalculatedValue] From [AnotherTable]);
UPDATE a
SET AColumn = @v
FROM dbo.ATable AS a
INNER JOIN dbo.Member AS m
ON a.Member_Id = m.Id
WHERE m.Title = @title;
END
GO
现在称之为:
EXEC dbo.TargetSP @title = 'Example';
答案 4 :(得分:1)
DECLARE @VId BIGINT;
DECLARE [My_Cursor] CURSOR FAST_FORWARD READ_ONLY FOR
Select [M].[Id] From [Member] AS [M] Where [M].[Title] = 'Example'
OPEN [My_Cursor]
FETCH NEXT FROM [My_Cursor] INTO @VId
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC [TargetSp]
@Id = @VId
FETCH NEXT FROM [My_Cursor] INTO @VId
END
CLOSE [My_Cursor]
DEALLOCATE [My_Cursor];
GO
答案 5 :(得分:0)
如果参数是整数,则一次只能传递一个值。
您的选择是:
关于性能问题,重新编写proc以迭代id列表比调用它几次更快,每个id一次,但是除非你正在处理一个巨大的id列表,我不认为你会看到很多不同