Domanda

che sto cercando di fare molte domande differenti su una lista di prodotti che ha una molto di grandi dimensioni ora di creazione. Per ottenere miglioramenti delle prestazioni desidero utilizzare una tabella temporanea e solo fare molte domande su questo tabella temporanea.

Sembra piuttosto standard. Eppure io sto lottando per condividere questo tabella temporanea in SQL dinamico. A quanto mi risulta, ciascun oggetto SqlCommand eseguito nel proprio filo e quindi la tabella temporanea è in un ambito diverso -. Rendendo così inaccessibile dal filo di query

Ho provato ad utilizzare una tabella temporanea globale e che funziona benissimo, ma non è l'ideale?

Come posso condividere una tabella temporanea locale tra le query SQL dinamiche?

Il mio intento:

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
È stato utile?

Soluzione

Si potrebbe provare a utilizzare una tabella temporanea globale (ad esempio, l'uso ##MyTemp piuttosto che #MyTemp nelle query), con questo avvertimento :

  

tabelle temporanee globali sono   automaticamente caduto quando la sessione   che ha creato le estremità della tabella e tutti   altri compiti hanno smesso di riferimento   loro. L'associazione tra un compito   e una tabella viene fornita solo per la   la vita di un singolo Transact-SQL   dichiarazione. Ciò significa che a livello globale   tabella temporanea è caduto al   completamento dell'ultimo Transact-SQL   dichiarazione che era attivamente   riferimento alla tabella quando la   creando seduta è terminata.


EDIT:. Spiacenti, perse il fatto che hai già provato tabelle temporanee globali

Come di spostare tutta la tua logica in un unico stored procedure che crea / popola la tabella temporanea e quindi esegue le query e restituisce più gruppi di risultati per il codice del client?

Altri suggerimenti

Lo so che è un po 'che questa è stata pubblicata, ma la risposta, credo, è abbastanza semplice.

Suppongo si utilizza il MS Enterprise Library per accedere al database, questo spiega perché la tabella temporanea non esiste tra i comandi. La Biblioteca Enterprise chiude esplicitamente la connessione al DB (lo rimette in piscina) Al termine di comando. A meno che non si mette i comandi in una transazione. Se si utilizza ADO.NET direttamente (con l'apertura del collegamento, la costruzione e l'esecuzione dei comandi, quindi chiudere la connessione) non si ottiene questo problema (che è fino a quando la connessione si chiude - che è più rischioso). Ecco alcuni codice scritto utilizzando il MS Enterprise Library e una transazione (mi dispiace, 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.

Se si dovesse prendere la portata dell'operazione, il codice fallirebbe sul conteggio Select (*) come la tabella non esiste più. Specificando la portata mantiene la connessione aperta tra le chiamate di comando.

Spero che questo aiuta qualcuno.

Neil.

Ciò che manca dalla tua domanda è il ciclo di vita della tabella creata. Se lo avrete attaccare in giro per un po ', allora non è piuttosto una tabella temporanea, si tratta di un tavolo di lavoro che si popolano e utilizzare. Non vorrei usare una tabella temporanea a tutti, solo una tabella normale che viene creato dal SELECT INTO e usate da tutti gli altri fino a quando non viene scartato (se mai).

Un'alternativa che ho usato con successo è quello di creare un tavolo di lavoro in tempdb, e usarlo come se fosse una tabella temporanea globale (ad esempio, "TempDb.dbo.MyTable"). Ricordate che l'utente le tabelle vengono eliminate quando SQL Server viene riavviato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top