ストアドプロシージャを異なるユーザーが同時に実行できる場合は、一時テーブルを使用することをお勧めしますか?


8

ActiveGUIDからobjectGUIDを取得するストアドプロシージャに取り組んでいます。結果を一時テーブルに格納し、他のプロセスで使用するために出力パラメーターに値を返します。SPは、さまざまなストアドプロシージャ、およびWebアプリケーションのPHP、ASP Classic、ASP.Netから呼び出されます。

私はそれをここに読んだ(一時テーブルに関して):

ストアドプロシージャ内で作成された場合、それらはストアドプロシージャの完了時に破棄されます。さらに、特定の一時テーブルのスコープは、それが作成されたセッションです。つまり、現在のユーザーにのみ表示されます。複数のユーザーが#TableXという名前の一時テーブルを作成でき、同時に実行されるクエリは互いに影響しません。ユーザーは自律型トランザクションのままであり、テーブルは自律型オブジェクトのままです。サンプルの一時テーブル名が「#」記号で始まっていることに気付くでしょう。

私は行ってもいいように思えますが、私が知らない落とし穴がないことを確認するためにいくつかのアドバイスを求めたかったのです。こちらがSPです。

前もって感謝します。

CREATE PROCEDURE stp_adlookup
@user varchar(100),
@objectGUID varbinary(256) OUTPUT
AS
SET NOCOUNT ON;
DECLARE @qry char(1000)
CREATE TABLE #tmp(
objectGUID nvarchar(256)
)

SET @qry = 'SELECT *
FROM openquery(ADSI, ''
SELECT  objectGUID              
FROM    ''''LDAP://mydomaincontroller.com''''
WHERE sAMAccountName = ''''' + @user + '''''
'')'
INSERT INTO #tmp
EXEC(@qry)
SELECT @objectGUID=CAST(objectGUID as varbinary(256))  FROM #tmp;
DROP TABLE #tmp
SET NOCOUNT OFF;
GO

回答:


15

はい。ユーザーがまったく同じ時刻で実行されている場合でも、各ユーザーは#tempテーブルの独自のコピーを取得します。

(ただし、先頭に2つのポンド記号/ハッシュ記号で示されるグローバル## tempテーブルを使用しないでください。)

しかし、なぜここに#tempテーブルが必要なのでしょうか。このようなものが機能するはずです(私は私の近くにLDAPを持っていないため、期待外れです)。

CREATE PROCEDURE dbo.stp_adlookup -- ALWAYS use schema prefix
  @user varchar(100),
  @objectGUID varbinary(256) OUTPUT
AS
BEGIN -- use body wrappers
  SET NOCOUNT ON;

  DECLARE @qry nvarchar(max); -- don't use CHAR for dynamic SQL

  SET @qry = N'SELECT @o = objectGUID
    FROM openquery(ADSI, ''SELECT  objectGUID              
      FROM    ''''LDAP://mydomaincontroller.com''''
      WHERE sAMAccountName = ''''' + @user + ''''''')';

  -- can probably parameterize the above, but those single
  -- quotes are a nightmare. Not sure if they're necessary
  -- but I do not feel like trying to untangle them.

  EXEC sys.sp_executesql @qry, N'@o UNIQUEIDENTIFIER', @o = @objectGUID OUTPUT;

  -- SET NOCOUNT OFF; -- don't do this.
END
GO

8

問題はありません。同じ名前の一時テーブルを使用して1日に数千回実行されるSPが無数にあり、問題はありません。

これは視覚的な例です。SQL2014インスタンスに2つのテーブルを作成しました。1つはSPID 53から作成され、もう1つはSPID 57から作成されました。オブジェクトエクスプローラーでの表示は次のとおりです。

ここに画像の説明を入力してください

ご覧のとおり、「名前」は同じですが、最後には、テーブルを異なるようにする素敵な文字のセットがあります。唯一の違いは、異なるクエリウィンドウからCREATEステートメントを実行したことです。これは、視覚的に表示する方法です。#tmpテーブルをクエリする場合、セッションに適用されるテーブルのみをクエリします。

しかし、私は一つの提案をします。それは私が完全に罪を犯していることであり、私は移行に取り組んでいます。のsp_executesql代わりに使用しますEXEC()。アーロン・バートランドはこれを「キックへの悪い習慣」の一つとして書いた:

基本的に、sp_executesqlを使用すると、SQLインジェクションの可能性が減り、実行プランが再利用される可能性が高くなります。アーロンはこの記事でより詳細に説明していますが、それは1000フィートのビューです。


5
同じ名前のローカル一時テーブルをすでに作成している別のプロシージャからプロシージャが呼び出される可能性があるため、プロシージャごとにローカル一時テーブルに一意の名前を付けると便利な場合があることを付け加えます。
ポールホワイト9

2

広義では、この方法で問題なく実行できます。ストアドプロシージャのスコープは限られているため、(例)3人のユーザーが同じストアドプロシージャを実行し、一時テーブルが混在しない場合でも、お互いを見ることはできません。

別のセッションまたは別のプロセスを実行しているユーザーと結果を共有する必要がない限り、Tempテーブルは完全に適切な方法です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.