Sql Server:索引已存在于全局临时表中

时间:2017-03-06 12:25:00

标签: sql sql-server stored-procedures temp-tables global-temp-tables

在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(ZERO)行。

应用程序调用存储过程:此应用程序通常在早上启动并在晚上关闭。

理论上,可能存在冲突,用户尝试插入数据并创建索引,而另一个人已经在做同样的事情。但它不太可能始终发生在同一个用户身上;如果该用户在几分钟后再次尝试(表和索引已经存在),则应该是不可能的。

这适用于所有用户(接近100),但是一个持续收到错误的特定用户:The operation failed because an index or statistics with name 'IX_MyTable' already exists on table ##MyTable

除了我已经考虑过将全球临时表定为常规表之外,有人可以向我解释一下这种行为吗?

提前感谢任何有帮助的人!

3 个答案:

答案 0 :(得分:3)

在这种情况下,您会遇到这种情况:

  1. 您创建表格。它是空的。
  2. 运行insert查询,但不插入任何行。
  3. 创建索引。
  4. 在下一次运行中,您将有一个空表并再次尝试insert

    这很容易解决。只需使用try / catch块或测试,即可在创建索引之前查看索引是否存在。或者,更好的是,在创建表时创建索引。除非您插入大量数据,否则开销不会太糟糕。

答案 1 :(得分:1)

错误解释了自己,你必须在创建表时创建索引,当它已经存在时你不能创建索引

IF OBJECT_ID ( 'tempdb..##MyTable' ) IS NULL
Begin
CREATE TABLE ##MyTable
(
    Key1 smallint
  , Key2 nvarchar(16)
  , Value1 char(3)
);
CREATE NONCLUSTERED INDEX IX_MyTable ON ##MyTable ( [Key1], [Key2] );
END 

在您的存储过程中,当表为空时,您正在创建索引内部条件,因此每次从表中删除所有数据时,它都会尝试创建索引。

答案 2 :(得分:1)

如果您在表创建块本身中移动Create Index语句,那就更好了。

IF OBJECT_ID ( 'tempdb..##MyTable' ) IS NULL
BEGIN
    CREATE TABLE ##MyTable
    (
        Key1 smallint
      , Key2 nvarchar(16)
      , Value1 char(3)
    );
    CREATE NONCLUSTERED INDEX IX_MyTable ON ##MyTable ( [Key1], [Key2] ); 
END