1

我有一个存储过程,它有一个名为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或在目标脚本中重写它是否有任何性能差异?

4

6 回答 6

3

您可以使用表值参数(请参阅http://msdn.microsoft.com/en-us/library/bb510489.aspx)。通常,如果您只向服务器发送一个请求而不是请求列表,您将看到更短的执行时间。

于 2012-04-23T12:05:53.337 回答
1

由于您只关心标题为“示例”的所有行,因此您不需要先确定列表,然后告诉 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';
于 2012-04-23T13:39:59.867 回答
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
于 2012-04-23T13:48:53.413 回答
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
于 2012-04-23T12:44:06.163 回答
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
于 2012-04-23T12:12:08.007 回答
0

如果参数是整数,则一次只能传递一个值。

您的选择是:

  1. 多次调用proc,每个参数一次
  2. 更改 proc 以接受一种结构,您可以在该结构中传递多个 id,例如传递逗号分隔的值列表(不太好)或表值参数的 varchar

关于性能问题,重写 proc 以遍历 id 列表比调用它几次(每个 id 一次)要快,但除非你正在处理一个巨大的 id 列表,否则我认为你不会看到差别很大

于 2012-04-23T12:26:27.973 回答