【问题标题】:Scope of Derived Tables in SQL ServerSQL Server 中派生表的范围
【发布时间】:2024-01-02 16:27:01
【问题描述】:

我最近一直在研究 SQL 并进行了一些探索。关于临时表,我发现了 3 种不同的临时表类型:

1) 创建表#TempTable

2) 声明表@TempTable

3) SELECT * FROM (SELECT * FROM Customers) AS TempTable

现在我了解了 #TempTable 和 @TempTable 类型背后的范围,但是示例 3 中的派生表呢?这个派生表存储在哪里?如果它是在 1 个事务中声明的,那么第二个事务是否可以访问它,或者派生表的范围与示例 1 和示例 2 相同?

【问题讨论】:

  • 你漏掉了一些,看我的回答
  • 如果您更喜欢我的答案,可以将您接受的答案改为我的。
  • 虽然你添加了额外内容,但我最初的问题得到了马克的回答:)

标签: sql sql-server scoping temp-tables


【解决方案1】:

1) CREATE TABLE #TempTable --local 临时表

本地临时表仅在当前会话中可见,并且可以在嵌套存储过程调用之间共享:http://www.sommarskog.se/share_data.html#temptables

2) DECLARE TABLE @TempTable --本地表变量

局部变量的范围是声明它的批处理、存储过程或语句块。它们可以作为过程之间的参数传递。它们不受事务的约束,并将在回滚后保留所有行。

3) SELECT * FROM (SELECT * FROM Customers) AS TempTable --派生表

仅对当前查询可见

4) CREATE TABLE ##TempTable --global temp table

这与#temp 表的不同之处在于它对所有进程都是可见的。当创建过程结束时,表被删除(但会等到其他进程的任何当前活动完成)。

5) CTE - 公用表表达式

示例 CTE:

;WITH YourBigCTE AS
(
    big query here

)
SELECT * FROM YourTable1  WHERE ID IN (SELECT ID FROM YourBigCTE)
UNION 
SELECT * FROM YourTable2  WHERE ID IN (SELECT ID FROM YourBigCTE)

可以在同一个 CTE 命令中多次使用,甚至可以递归使用,并且将持续到 CTE 命令的持续时间。

【讨论】:

    【解决方案2】:

    这取决于您使用的实际 RDBMS - 我将假设 Sybase 或 SQL Server(但可能对所有人都适用)

    SELECT * FROM (SELECT * FROM Customers) AS TempTable
    

    Temptable 仅适用于当前 SQL 语句,即仅适用于 select。

    SELECT * FROM Customers into tempdb..TempTable
    

    将在 tempdb 中创建一个必须显式删除的新表

    【讨论】:

    • 这样就具有与第 1 点示例中相同的范围,谢谢队友!
    • 否 - #tempTable 持续会话/连接 - 选择只针对一个选择,选择进入是全局的