【问题标题】:Excel - SQL Query - ## Temp TableExcel - SQL 查询 - ## 临时表
【发布时间】:2019-01-10 04:49:43
【问题描述】:

我正在尝试使用一个查询的结果创建一个全局临时表,然后可以将其选为一个表并进一步操作多次,而无需一遍又一遍地重新处理数据。

这在SQL management studio中完美运行,但是当我尝试通过Excel查询添加表时,当时可以引用该表,但它不是在tempdb数据库的Temporary Tables中创建的。

我已经把它分解成一个简单的例子。

如果我在 SQL management studio 中运行,结果为 1 会按预期返回,并在 Temporary Tables 中创建表 ##testtable1

set nocount on;

select 1 as 'Val1', 2 as 'Val2' into ##testtable1
select Val1 from ##testtable1

然后我可以在这个表上运行另一个选择,即使在不同的会话中,正如你所期望的那样。例如

Select Val2 from ##testtable1

如果我不删除 ##testtable1,则在 Excel 中的查询中运行以下命令将返回 2 的结果,如您所料。

Select Val2 from ##testtable1

但是,如果我直接在 Excel 中将相同的 Select... 运行到 ##testtable1 查询中,则会正确返回 1 的结果,但不会创建临时表。

如果我然后尝试运行

Select Val2 from ##testtable1

作为一个单独的查询,它错误地说“无效的对象名称'##testtable1'

该表未列在 SQL 管理工作室的临时表中。

就好像在查询完成后它正在对表执行删除一样,即使我没有调用删除。

我该如何解决这个问题?

【问题讨论】:

  • 为什么首先需要一个全局临时表?它们充满了并发问题。请记住,当使用它的最后一个连接关闭时,全局表将被删除。这意味着如果您在 Excel 中创建但不使用它,则临时表不会无限期地挂起。
  • 只是为了强调@SeanLange 已经提到的内容:SSMS(能够)保持会话打开,而 Excel 不能。每次发送查询时,都会创建一个新会话并立即再次关闭(一旦查询完成)。
  • 最终这是为属于母公司的 5 个品牌创建财务资产负债表报告。每个品牌都是一个单独的数据库。有 5 个查询返回结果,然后需要进一步处理以将它们全部加在一起作为“组总数”。没有理由不能在一个查询中全部完成,但 5 个查询中的每一个都有 22,000 个字符长,因此将它们加在一起会使我超过 .ConnectionString 字符限制。以这种方式在 Management Studio 中完美运行,它只是试图通过 Excel 进行数据处理。
  • 你要关闭每个通话之间的连接吗?你用的是哪个版本的excel?您是否为此或 vba 使用 excel 中的内置查询工具?最后一个问题:您可以创建一个视图或存储过程来执行此操作吗?如果需要,这些可以跨越多个数据库:D

标签: sql-server excel


【解决方案1】:

阅读全局临时表 (GTT)。只要有会话引用它,它们就会一直存在。在 SSMS 中,如果在另一个会话中使用之前关闭创建 GTT 的会话,则 GTT 将被丢弃。这就是 Excel 中正在发生的事情。 Excel 创建连接、执行和断开连接。由于 Excel 断开连接时没有使用 GTT 的会话,因此 GTT 被丢弃。

我强烈建议您创建一个普通表而不是使用 GTT。由于它们的临时性和对活动会话的依赖性,使用 GTT 时可能会得到不一致的结果。如果您改为创建普通表,则可以确定它在以后尝试使用时仍然存在。

创建/清理表的代码非常简单。

IF OBJECT_ID('db.schema.tablename') IS NOT NULL
    TRUNCATE TABLE [tablename]
ELSE
    CREATE [tablename]...
GO

您可以将截断更改为删除以清理一组特定的数据并将其放在每个查询的开头。

【讨论】:

  • 感谢您的建议 :) 通过使用普通表格,我已经完全按照我的意愿工作了。我一用完就叫它放在桌子上。
【解决方案2】:

你可以使用视图吗?假设您连接到同一台服务器上的 5 个数据库,您可以将数据合并到一个视图中:

    CREATE VIEW [dbo].[testView]
    AS
    SELECT        *
    FROM            database1.dbo.myTable
    UNION
    SELECT        *
    FROM            database2.dbo.myTable

然后在excel中:

数据> 新查询 > 从数据库 > 从 SQL Server 数据库

进入数据库服务器

从适当的数据库中选择视图 - 完成:)

或调用视图,但你正在这样做(例如 vba 等)

同样,您可以使用存储过程并从 VBA 调用它..基本上任何将更多复杂性转移到服务器端以使您的生活更轻松的东西:D

【讨论】:

    【解决方案3】:

    你绝对可以做到这一点。请注意我是如何从名为“TmpSql”的 SQL 中构建一个临时表的……这可以是您想要的任何查询。然后我将它设置为记录集 1。然后我创建另一个记录集 2,它会获取临时表数据。

    想象一下,如果您在第一个 cn.Execute 上循环,其中 TmpSql 正在更改。这允许您构建一个来自许多来源或更改变量的临时表。这是一个强大的解决方案。

    cn.open "Provider= ..."
    
    sql = "Select t.* Into #TTable From (" & TmpSql & ") t "
    Set rs1 = cn.Execute(sql)
    
    GetTmp = "Select * From #TTable"
    rs2.Open GetTmp, cn, adOpenDynamic, adLockBatchOptimistic
    If Not rs2.EOF Then Call Sheets("Data").Range("A2").CopyFromRecordset(rs2)
    
    rs2.Close
    rs1.Close
    
    cn.Close
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-26
      • 2013-07-01
      • 2013-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多