在 Sql Server 2012 SP3 v.11.0.6020.0 (X64) 中,我有一个存储过程,用于测试全局临时表(例如 ##MyTable
)是否存在并创建它 -当然,如果没有找到。
IF OBJECT_ID ( 'tempdb..##MyTable' ) IS NULL
CREATE TABLE ##MyTable
(
Key1 smallint
, Key2 nvarchar(16)
, Value1 char(3)
);
在此过程的后面,它会测试表是否有行,并在必要时填充它。
IF NOT EXISTS ( SELECT * FROM ##MyTable )
BEGIN
INSERT INTO ##MyTable
SELECT Key1, Key2, Value1
FROM SourceTable
WHERE ...
CREATE NONCLUSTERED INDEX IX_MyTable ON ##MyTable ( [Key1], [Key2] );
END
我确信 Key1 和 Key2 是唯一的,因为它们是源表上的主键。
然后,无论哪种情况(表已存在或不存在),存储过程都会查询该表。不用说,sp逻辑比这复杂得多。
该表填充了来自 7 个不同来源的客户数据;通常,插入近 100 万行需要几秒钟的时间。理论上,所有 INSERT INTO ##MyTable 都不可能插入 0 (零) 行。
存储过程由应用程序调用:该应用程序通常在早上启动,晚上关闭。
理论上,可能会出现冲突,一个用户尝试插入数据并创建索引,而另一个用户已经在做同样的事情。但这种情况不太可能总是发生在同一个用户身上;如果该用户几分钟后再次尝试(表和索引已经存在),那应该是不可能的。
这对于所有用户(接近 100)来说都可以正常工作,但对于特定用户来说,他会不断收到错误: 操作失败,因为表 ##MyTable 上已存在名为“IX_MyTable”的索引或统计信息
.
除了我已经在考虑将全局临时表变成常规表这一事实之外,有人可以向我解释一下这种行为吗?
预先感谢任何愿意提供帮助的人!
最佳答案
在这些情况下您会遇到此行为:
- 您创建表格。里面是空的。
insert
查询已运行,但未插入任何行。- 索引已创建。
在下次运行时,您将有一个空表并尝试 insert
再次。
这很容易解决。只需使用 try
/catch
在创建索引之前阻止或测试索引是否存在。或者,更好的是,在创建表时创建索引。除非您插入大量数据,否则开销应该不会太严重。
关于sql服务器: index already existing on global temp table,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42625611/