sql服务器: index already existing on global temp table

标签 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 (零) 行。

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

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

这对于所有用户(接近 100)来说都可以正常工作,但对于特定用户来说,他会不断收到错误: 操作失败,因为表 ##MyTable 上已存在名为“IX_MyTable”的索引或统计信息.

除了我已经在考虑将全局临时表变成常规表这一事实之外,有人可以向我解释一下这种行为吗?

预先感谢任何愿意提供帮助的人!

最佳答案

在这些情况下您会遇到此行为:

  1. 您创建表格。里面是空的。
  2. insert查询已运行,​​但未插入任何行。
  3. 索引已创建。

在下次运行时,您将有一个空表并尝试 insert再次。

这很容易解决。只需使用 try/catch在创建索引之前阻止或测试索引是否存在。或者,更好的是,在创建表时创建索引。除非您插入大量数据,否则开销应该不会太严重。

关于sql服务器: index already existing on global temp table,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42625611/

相关文章:

sql - 如何使用 ‘ORDER BY’ 和 ‘LIMIT’ 语句在 MYSQL 5.1 中进行多表 UPDATE

mysql - (My)SQL 左/右/内连接方向

sql - 在 SQL Server 中的另一个存储过程中执行一个存储过程

sql-server - 如何访问在另一个存储过程中创建的存储过程中的临时表?

mysql - 如何用 JOIN 重写这个语句,使其更快?

sql - Postgres : What is the query 'select * from user' actually doing?

sql-server - sqlmetal 无法用全文提取 udf

sql - SSDT Schema Compare不断为用户寻找差异?

sql - 在不存在的地方插入值

stored-procedures - 使用 SQL 与 Java 编写 DB2 存储过程有何优缺点?