質問

結果セットに対してさまざまなクエリを実行しようとしています。 とても 作成時間が長くなる。パフォーマンスを向上させるために、一時テーブルを使用し、この一時テーブルに対して多くのクエリを実行したいと考えています。

かなり標準的なようです。それでも、この一時テーブルを動的 SQL で共有するのに苦労しています。私の理解では、各 SqlCommand オブジェクトは独自のスレッドで実行されるため、一時テーブルは異なるスコープ内にあり、クエリ スレッドからアクセスできなくなります。

グローバル一時テーブルを使用してみましたが、うまく機能しましたが、理想的ではありませんか?

動的 SQL クエリ間でローカル一時テーブルを共有するにはどうすればよいですか?

私の意図:

using (var conn = new SqlClient.SqlConnection("..."))
{
    // Creation involes many table joins in reality
    String creationScript = "SELECT * FROM FooTable INTO #MyTemp";
    SqlCommand createTempTbl = new SqlCommand(creationScript, conn);
    createTempTbl.ExecuteNonQuery();

    String query1 = "SELECT * FROM #MyTemp where id=@id";
    SqlCommand query1Comm = new SqlCommand(query1, conn);
    query1Comm.Parameters.Add("@id", ...);

    String query2 = "SELECT * FROM #MyTemp where name=@name";
    SqlCommand query2Comm = new SqlCommand(query2, conn);
    query2Comm.Parameters.Add("@name", ...);

    // And so on the queries go

} // Now want #MyTemp to be destroyed
役に立ちましたか?

解決

グローバル一時テーブルを使用してみることもできます(つまり、 ##MyTemp それよりも #MyTemp あなたのクエリで)、 この警告とともに:

テーブルを作成したセッションが終了し、他のすべてのタスクがそれらの参照を停止すると、グローバルな一時テーブルが自動的に削除されます。タスクとテーブルとの関連は、単一のTransact-SQLステートメントの寿命のためにのみ維持されます。これは、作成セッションが終了したときにテーブルを積極的に参照していた最後のTransact-SQLステートメントの完了時に、グローバルな一時テーブルがドロップされることを意味します。


編集: おっと、グローバル一時テーブルをすでに試しているという事実を見逃していました。

すべてのロジックを単一のストアド プロシージャに移動して、一時テーブルを作成/設定し、クエリを実行して複数の結果セットをクライアント コードに返すのはどうでしょうか。

他のヒント

私はこの1つが投稿されましたので、それはしばらくのです知っているが、答えは、私は信じて、非常に簡単です。

一時テーブルは、コマンドの間に存在しない理由

私はあなたがデータベースにアクセスするためのMSエンタープライズライブラリを使用していると推測、これは説明します。エンタープライズライブラリは、明示的にDBへの接続(プールに戻ってそれを置く)コマンドが終了を閉じます。あなたがトランザクションにコマンドを入れない限りそれは、あります。 あなたは(そして、接続を閉じ、コマンドを構築し、実行し、接続を開くことによって)直接ADO.NETを使用する場合は、この問題を得ることはありません(接続が閉じたとき、それはあなた次第です - より危険です)。 ここではMSエンタープライズライブラリとトランザクション(申し訳ありませんが、VB.NET)を使用して書かれたいくつかのコードがあります:

' Get a reference to the database
Dim sqlNET As New Sql.SqlDatabase("*Your Connection String Here...*")

' Specify the transaction options
Dim oTranOpt As TransactionOptions = New TransactionOptions
' What type of isolation the transaction should have (V. Important):
oTranOpt.IsolationLevel = IsolationLevel.ReadUncommitted ' This one doesn't place locks on DB but allows dirty reads
' How long the transaction has to complete before implicitly failing (h,m,s):
oTranOpt.Timeout = New TimeSpan(0, 0, 30)

' Start the scope of the transation
Using oTranScope As TransactionScope = New TransactionScope(TransactionScopeOption.Required, oTranOpt)

    ' Create the connection to the DB. Not abs. necessary. EL will create one but best to do so.
    Using Conn As Common.DbConnection = sqlNET.CreateConnection

        ' Create a Temp Table
        sqlNET.ExecuteNonQuery(CommandType.Text, "SELECT * INTO #MyTemp FROM FooTable")

        ' Get results from table, e.g.
        Dim intCount As Integer = sqlNET.ExecuteScalar(CommandType.Text, "Select Count(*) from #MyTemp")

        MsgBox(intCount)

        ' Flag transaction as successful (causes a commit when scope is disposed)
        oTranScope.Complete()

    End Using ' Disposes the connection

End Using ' If this point is reached without hitting the oTranScope.Complete - the transaction is rolled back and locks, if any, are released.
あなたがトランザクション・スコープを取り出した場合は、

、コード表がもはや存在しないとして、SELECT COUNT(*)に失敗します。範囲を指定すると、コマンドの呼び出しの間オープン接続を維持します。

私は、これは誰かに役立ちます願っています。

ニールます。

どのようなご質問から欠落していることは作成したテーブルのライフサイクルです。あなたはそれがしばらくの間、周りに付着しなければならない場合、それは非常に一時テーブルではありません、それはあなたが移入して使用する作業テーブルです。それがドロップされるまで(これまでの場合)私は、全くSELECT INTOによって作成され、他の皆によって使用されます普通のテーブルを一時テーブルを使用することはありません。

私が正常に使用してきた代替は、tempdb内のワークテーブルを作成し、それがグローバル一時テーブル(例えば、「TempDb.dbo.MyTable」)であるかのようにそれを使用することです。テーブルは、SQL Serverの再起動時に破棄され、そのユーザーを覚えています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top