1

次の名前の引数を持つストアド プロシージャがありますId

CREATE PROCEDURE [TargetSp](
   @Id  [bigint]
)
AS 
BEGIN
   Update [ATable]
   SET [AColumn] = 
   (
     Select [ACalculatedValue] From [AnotherTable]
   )
   Where [ATable].[Member_Id] = @Id
END

したがって、次のような1つのIDではなく、IDのリストに使用する必要があります。

Exec [TargetSp]
  @Id IN (Select [M].[Id] From [Member] AS [M] Where [M].[Title] = 'Example');

最初: リストに対して実行するにはどうすればよいですか?

2番目:spを何度も実行するか、ターゲットスクリプトで書き直すかでパフォーマンスに違いはありますか?

4

6 に答える 6

3

テーブル値のパラメーターを使用できます(http://msdn.microsoft.com/en-us/library/bb510489.aspxを参照)。一般に、リクエストのリストではなく1つのリクエストのみをサーバーに送信すると、実行時間が短くなります。

于 2012-04-23T12:05:53.337 に答える
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 に答える
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';
于 2012-04-23T13:39:59.867 に答える
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

興味深いことに、私は数千人のユーザーがいる大規模なシステムで作業を行ったところ、この方法を使用すると、ID の小さなリスト (たとえば ID が 5 つ以下) に対してテーブル値パラメーター アプローチよりも優れていることがわかりました。テーブル値パラメーター アプローチは、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
 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 に答える
0

パラメータが整数の場合、一度に渡すことができる値は 1 つだけです。

オプションは次のとおりです。

  1. パラメータごとに1つずつ、procを数回呼び出します
  2. コンマで区切られた値のリスト(あまり良くない)またはテーブル値パラメーターを渡すvarcharのような複数のIDを渡すことができる構造を受け入れるようにprocを変更します

パフォーマンスの問題については、ID ごとに 1 回、複数回呼び出すよりも、ID のリストを反復処理するように proc を書き直した方が高速ですが、ID の巨大なリストを扱っていない限り、多くの違い

于 2012-04-23T12:26:27.973 に答える