SQL Server中的全局临时表

5

我有一个##表格,可以在所有会话中访问,但有时会出现错误。

数据库中已经存在一个名为'##table'的对象。

为什么会出现这种情况,如何解决。

3个回答

8

发现了一个有趣的参考资料(已删除引用现在是恶意网站的过时URL):

全局临时表的操作方式与本地临时表类似;它们在tempdb中创建,导致的锁定和日志记录比永久表少。然而,它们对所有会话都可见,直到创建会话超出范围(并且其他会话不再引用全局##temp表)。如果两个不同的会话尝试上述代码,则如果第一个仍然处于活动状态,则第二个将收到以下消息:

服务器:Msg 2714,级别16,状态6,行1 数据库中已经存在名为“##people”的对象。

我还没有看到使用全局##temp表的有效理由。如果数据需要持续存在于多个用户中,则至少对我来说,使用永久表更有意义。您可以通过永久表拒绝权限;您无法拒绝用户从全局##temp表中访问。


2
回复:“我还没有看到使用全局##temp表的有效理由” 当我想在动态SQL中创建一个表并在外部范围中访问它时,我会使用全局临时表。顺便说一下,那篇文章传播了旧神话,即表变量在内存中,而#temp表在磁盘上。在这方面两者之间实际上没有太大(或没有)区别。 - Martin Smith
2
我考虑不包括第二段,因为它与问题没有直接关系。但第一段确实讨论了Jeevan所描述的确切问题。 - Chris Porter

3
There is already an object named '##table' in the database.

如果您执行CREATE TABLE语句,而数据库中已经存在'##table',则通常会出现此错误。

在您的代码中,可能会再次调用创建此全局表的CREATE TABLE逻辑,导致出现此错误。

您是否有导致此错误的确切语句的详细信息?


3

这个是线程安全的吗?当其他会话尝试做相同的事情,并且在第一个会话创建表之前的某个地方创建该表时,它是如何避免竞态条件的? - alpav
@alpav 它不能避免竞态条件,因此如果两个线程恰好在同一时间创建临时表,其中一个将失败。 - Neal Xiong
鉴于SQL Server是符合ACID标准的数据库,我认为竞态条件通过底层系统表上的锁定机制来管理对象名称得到了缓解。这种假设可能是错误的,但如果是这样的话,我很想看到一个无法成功的重现。 - Ben Thul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接