【问题标题】:In MS SQL Server 2005, what happens when a temp table is being accessed by different executions of the same SP?在 MS SQL Server 2005 中,当同一个 SP 的不同执行访问临时表时会发生什么?
【发布时间】:2013-11-09 08:36:52
【问题描述】:

我有一个存储过程,它首先检查临时表 (#temp_table),如果存在则将其删除,然后使用该表,最后在完成后将其删除。当用户执行某些操作来触发它时,该 SP 会被随机调用,并且有时该 SP 可能会同时执行 - 或有一些重叠。

假设我让同一个 SP 的 Exec1 和 Exec2 创建、更改和删除 #temp 表,并且它们彼此在几毫秒内运行。

会发生什么? Exec1 会锁定 #temp_table 并且 Exec2 会在 Exec1 完成时等待吗?在我的情况下,这显然是可取的。我不希望 Exec1 和 2 同时使用该表,也不希望 Exec2 失败,因为 Exec1 已经在使用该表。

[编辑] 我应该将我的临时表转换为表变量吗?

【问题讨论】:

    标签: sql-server temp-tables table-locking


    【解决方案1】:

    在 sql server 中,如果您创建一个本地临时表,它带有一个 # 符号 sql server 在后端使用一些下划线和一些 ID。假设您在 temp db 中创建了一个名称为 #Temp 的 Temp 表 sql server 创建了一个名称为 #Temp_______10912098 的表,在单独的连接中创建的每个 Temp 表的名称末尾都会有其 on ID。


    这些是在不同连接中创建的所有临时表都具有名称#Temp,但附加了一些下划线和unique id sql server 用于区分它们。

    【讨论】:

    • 所以在我的 SP 中我有 IF OBJECT_ID('tempdb..#temp_table') IS NOT NULL DROP TABLE #temp_table 这什么都不做吗?或者这可能会对其他处决产生不利影响?
    • 如果您每次都从新会话(例如,从 Web 应用程序)调用它,则不需要它,因为临时表的范围仅限于会话。有关更多信息,请参阅我的答案。
    • 您不需要像 Dommer 所说的那样,但在尝试创建 OBJECT 之前检查它的存在始终是一个好习惯。将那段代码保留在您的过程中。
    【解决方案2】:

    临时表#table 的范围仅限于您的会话,因此应该没有问题。

    如果您使用##table,那么这是全球性的,您会遇到问题。

    请看这里:MSDN SQL Tables

    具体一点:

    如果数据库会话创建本地临时表#employees, 只有 session 可以与 table 一起工作,并且当它被删除时 会话断开。如果创建全局临时表 ##employees,数据库中的任何用户都可以使用此表。如果创建后没有其他用户使用此表,则该表为 断开连接时删除。如果另一个用户使用该表 创建后,SQL Server 会在您断开连接后将其删除,并且 在所有其他会话不再积极使用它之后。

    【讨论】:

      【解决方案3】:

      以散列 # 命名的临时表特定于单个连接。

      因此,如果两个连接(也称为“进程”或“SPID”)都通过相同的 #tablename 引用临时表,它们实际上将引用不同的表。

      如果您查看 tempdb,您可以看到这一点。将有多个表命名为#748B826C。这些实际上是临时表变量,例如 declare @t table (ix int identity primary key) 和带有哈希的临时表名称。

      所以如果这些是不同的连接而不是递归触发器,应该没有问题。

      但是,如果您担心递归触发器的可能性,您应该改用表变量。这些仅限于批处理或存储过程的范围。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-17
        • 2010-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多