web-dev-qa-db-ja.com

プロシージャの複数のインスタンスが同じ#Tempを同時に作成できますか?

#tempテーブルにデータを挿入する手順があります。データに特定の操作を行った後、#tempテーブルから他のテーブルにデータを格納します。

この手順の複数のインスタンスを同時に実行することはできません。どうして?複数のタブで同じ名前の#tempテーブルを作成します。それでは、一時テーブルの複数のインスタンスが同じことを実行できないのはなぜですか。

それに対する解決策はありますか?

例:

--exec dbo.testing_temp_table
CREATE PROCEDURE [dbo].[testing_temp_table]
AS
BEGIN

    SET NOCOUNT ON;

    -- Insert statements for procedure here
    IF OBJECT_ID('tempdb..#temp_1') IS NOT NULL drop table #temp_1
    select  * into #temp_1 from dbo.Emp

END
2
RISHABH GOYAL

「この手順の複数のインスタンスを同時に実行することはできません。なぜですか?」

実行できないとはどういう意味ですか、実行するとエラーが発生しますか?サーバーから煙は出ますか?

これで、IF OBJECT_ID()でストアドプロシージャ内のテーブルの存在を確認する必要がなくなりました。

SQL Serverは、ストアドプロシージャのインスタンスごとに一時テーブルのインスタンスを作成します。これは、作成スコープ(この場合はストアドプロシージャ)と、別のサブオブジェクトを呼び出す場合などの内部スコープにのみ表示されます。コード内のプロシージャ。手順が完了すると、一時テーブルはなくなります。

内部では、クエリプロセッサは、各インスタンスのTempDBのテーブル名に一意の文字列を追加します。

BOLにはすべての詳細があります: CREATE TABLE(Transact-SQL)

-同じサフィックスを生成するストアドプロシージャに関するOPコメントへの応答-ここではSQL Serverに十分なクレジットを与えていません。あなたの主張が真実なら、これは一時的なテーブルを使用するストアドプロシージャの複数のインスタンスを実行できず、地獄を引き起こしたであろう主要なバグだったでしょう。

私はあなたが単一の接続でそれをテストしていると思います、そして同じプロシージャの再実行時にあなたは同じサフィックスを得るのを見ます。これは、同じセッションから繰り返し実行するためにサフィックスを再利用するための最適化です。テストする必要があるのは:

CREATE PROCEDURE P 
AS
BEGIN
CREATE TABLE #T(Col1 INT);
WAITFOR DELAY '00:00:10';
SELECT * FROM TempDB.sys.tables;
END

そして、2つ以上の接続で、同時に実行します

EXEC P

ここに私のために思いついたものがあります:

name
#T____<Trimmed>_________000000000004
#T____<Trimmed>_________000000000005

HTH

7
SQLRaptor

あなたの問題はスコープです。上記の彼の応答では@SQLRaptorは完全に正しいですが、次のように見ると役立つ場合があります。

一時テーブルを作成すると、そのスコープはセッションに限定されます。つまり、セッションが閉じられるか、ユーザーまたはドロップするまで存在します。あなたが期待しているのは、テーブル変数と同じように、一時テーブルがストアドプロシージャ(そうではない)にスコープされることです。例:

-- Query window (otherwise known as session in this case)
Create #temp1 (temp table)
Create @temp1 (table variable)
     -- Run a stored procedure
     Create #temp2 (temp table)
     Create @temp2 (table variable)
     -- Currently all four exist.
-- On leaving the stored procedure the following exist:
-- #temp1
-- #temp2
-- @temp1
    -- Rerun the same stored procedure
    You attempt to create #temp2 but it fails because #temp2 still exists.

これで、セッション(クエリウィンドウ)を完全に離れると、すべてが消えます。

グローバル一時テーブルもあります。先頭に##が付いているもの。これらはすべてのセッションを対象としており、誰も使用していない場合にのみ使用できます。

基本的に、何らかの理由で一時テーブルを再利用する予定がない限り、SPの最後に一時テーブルをドロップします。このように:

--exec dbo.testing_temp_table
CREATE PROCEDURE [dbo].[testing_temp_table]
AS
BEGIN

    SET NOCOUNT ON;

    -- Insert statements for procedure here
    select  * into #temp_1 from dbo.Emp

    -- The rest of your code goes here

    DROP TABLE #temp_1
END
0
Kenneth Fisher