我试图做具有的非常的大创建时间的结果集合许多不同的查询。为了获得性能提升我希望用临时表,只是做该临时表许多查询。

似乎非常标准。然而,我很努力在动态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完成   这是积极的语句   当引用表   创建会话结束。


编辑:哎呀,忘记你已经尝试过全局临时表的事实。

如何所有的逻辑的移动到它创建/单个存储过程填充临时表,然后运行查询,并返回多个结果给客户端代码?

其他提示

我知道这是因为这一个被张贴了一段时间,但我相信答案是很简单的。

我猜测你是使用MS企业库访问数据库,这就解释了为什么临时表不命令之间存在。企业库明确的关闭到数据库的连接(把它放回池中)命令完成时。也就是说,除非你把命令放到交易。 如果您使用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