SQLステートメントは、SQL Serverの単一セッション内で同時に実行できますか?


16

一時テーブルを使用するストアドプロシージャを作成しました。SQL Serverでは、一時テーブルはセッションスコープであることを知っています。ただし、セッションで何ができるかについての明確な情報を見つけることができませんでした。特に、このストアドプロシージャが1つのセッションで2回同時に実行できる場合、2つの実行が一時テーブルを共有するため、そのプロシージャ内のトランザクションには非常に高い分離レベルが必要です。

回答:


19

ブレントの答えは、すべての実用的な目的のためにのために正しいこと、そしてこれは私が今までにおよそ誰かの心配を見てきたものではありませんが、それはあるセッションでストアドプロシージャの複数の呼び出しは、セッションスコープ#TEMPテーブルを介して相互に影響を与えることは可能。

良いニュースは、野生で起こる可能性は非常に低いことです。

1)ストアドプロシージャまたはネストされたバッチ内で宣言された#Tempテーブルには、セッションの可視性(または有効期間)はありません。そして、これらは、これまでで最も一般的なケース。

2)MultipleActiveResultsetsと非常に奇妙な非同期クライアントプログラミングが必要です。または、ストアドプロシージャが中間で結果セットを返すため、およびクライアントが最初の結果の処理中にストアドプロシージャの別のインスタンスを呼び出す必要があります。

これが不自然な例です:

using System;
using System.Data.SqlClient;

namespace ado.nettest
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var con = new SqlConnection("Server=localhost;database=tempdb;integrated security=true;MultipleActiveResultSets = True"))
            {
                con.Open();

                var procDdl = @"
create table #t(id int)
exec ('
create procedure #foo
as
begin
  insert into #t(id) values (1);
  select top 10000 * from sys.messages m, sys.messages m2;
  select count(*) rc from #t;
  delete from #t;
end
');
";
                var cmdDDL = con.CreateCommand();
                cmdDDL.CommandText = procDdl;
                cmdDDL.ExecuteNonQuery();

                var cmd = con.CreateCommand();
                cmd.CommandText = "exec #foo";
                using (var rdr = cmd.ExecuteReader())
                {
                    rdr.Read();

                    var cmd2 = con.CreateCommand();
                    cmd2.CommandText = "exec #foo";
                    using (var rdr2 = cmd2.ExecuteReader())
                    {

                    }

                    while (rdr.Read())
                    {

                    }
                    rdr.NextResult();
                    rdr.Read();
                    var rc = rdr.GetInt32(0);
                    Console.WriteLine($"Numer of rows in temp table {rc}");

                }


            }

            Console.WriteLine("Hit any key to exit");
            Console.ReadKey();
        }
    }
}

どの出力

Numer of rows in temp table 0
Hit any key to exit

ストアドプロシージャの2回目の呼び出しで行が挿入され、最初の呼び出しでクライアントが最初の結果セットから行をフェッチするのを待っている間に#tからすべての行が削除されたためです。最初の結果セットが小さい場合、行がバッファリングされ、クライアントに何も送信せずに実行が継続する可能性があることに注意してください。

あなたが移動した場合

create table #t(id int)

出力されるストアドプロシージャに:

Numer of rows in temp table 1
Hit any key to exit

そして、プロシージャ内で宣言さた一時テーブルで、2番目のクエリを

cmd2.CommandText = "select * from #t";

それは失敗します:

「無効なオブジェクト名「#t」。」

ストアドプロシージャまたはネストされたバッチ内で作成された#tempテーブルは、そのストアドプロシージャまたはバッチ、およびそれが呼び出すネストされたプロシージャとバッチでのみ表示され、プロシージャまたはバッチが終了すると破棄されるためです。


12

同時ではありません。次のオプションがあります。

  • 同じセッションで次々にクエリを実行する
  • 一時テーブルからグローバル一時テーブルに切り替える(#TableNameの代わりに## TableNameを使用)それへの参照
  • TempDBで実際のユーザーテーブルに切り替えます-テーブルを作成できますが、サーバーの再起動時にテーブルが消えることに注意してください
  • ユーザーデータベースの実際のユーザーテーブルに切り替える
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.