Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在表变量上创建索引_Sql_Sql Server_Tsql_Indexing_Table Variable - Fatal编程技术网

Sql 在表变量上创建索引

Sql 在表变量上创建索引,sql,sql-server,tsql,indexing,table-variable,Sql,Sql Server,Tsql,Indexing,Table Variable,能否在SQL Server 2000中为表变量创建索引 i、 e 我可以在名称上创建索引吗?这个问题被标记为SQL Server 2000,但为了方便使用最新版本的开发人员,我将首先解决这个问题 SQL Server 2014 除了下面讨论的添加基于约束的索引的方法之外,SQL Server 2014还允许在表变量声明上使用内联语法直接指定非唯一索引 下面是它的语法示例 /*SQL Server 2014+ compatible inline index syntax*/ DECLARE @T

能否在SQL Server 2000中为表变量创建索引

i、 e


我可以在
名称上创建索引吗?

这个问题被标记为SQL Server 2000,但为了方便使用最新版本的开发人员,我将首先解决这个问题

SQL Server 2014

除了下面讨论的添加基于约束的索引的方法之外,SQL Server 2014还允许在表变量声明上使用内联语法直接指定非唯一索引

下面是它的语法示例

/*SQL Server 2014+ compatible inline index syntax*/
DECLARE @T TABLE (
C1 INT INDEX IX1 CLUSTERED, /*Single column indexes can be declared next to the column*/
C2 INT INDEX IX2 NONCLUSTERED,
       INDEX IX3 NONCLUSTERED(C1,C2) /*Example composite index*/
);
过滤索引和包含列的索引当前不能使用此语法声明,但是SQL Server 2016将此语法进一步放宽。从CTP3.1开始,现在可以为表变量声明过滤索引。通过RTM,可能也允许包含列,但当前位置是


SQL Server 2000-2012

我可以在名称上创建索引吗

简短回答:是的

DECLARE @TEMPTABLE TABLE (
  [ID]   [INT] NOT NULL PRIMARY KEY,
  [Name] [NVARCHAR] (255) COLLATE DATABASE_DEFAULT NULL,
  UNIQUE NONCLUSTERED ([Name], [ID]) 
  ) 
下面是更详细的答案

/*SQL Server 2014+ compatible inline index syntax*/
DECLARE @T TABLE (
C1 INT INDEX IX1 CLUSTERED, /*Single column indexes can be declared next to the column*/
C2 INT INDEX IX2 NONCLUSTERED,
       INDEX IX3 NONCLUSTERED(C1,C2) /*Example composite index*/
);
SQL Server中的传统表可以具有聚集索引,也可以按以下方式构造

聚集索引可以声明为唯一以禁止重复键值,也可以默认为非唯一。如果不是唯一的,那么SQLServer会在任何重复的密钥中添加一个,以使其唯一

非聚集索引也可以显式声明为唯一。否则,对于非唯一的SQL Server(聚集索引键或堆)而言,这将再次确保它们是唯一的

在SQL Server 2000-2012中,只能通过创建
唯一
主键
约束隐式创建表变量的索引。这些约束类型之间的区别在于主键必须位于不可为null的列上。参与唯一约束的列可以为空。(尽管SQL Server在存在
NULL
s的情况下实现的唯一约束不符合SQL标准中的规定)。此外,表只能有一个主键,但有多个唯一约束

这两个逻辑约束都是通过唯一索引物理实现的。如果未明确指定,则
主键
将成为聚集索引和非聚集的唯一约束,但可以通过使用约束声明明确指定
聚集
非聚集
来覆盖此行为(示例语法)

由于上述原因,可以对SQLServer2000-2012中的表变量隐式创建以下索引

+-------------------------------------+-------------------------------------+
|             Index Type              | Can be created on a table variable? |
+-------------------------------------+-------------------------------------+
| Unique Clustered Index              | Yes                                 |
| Nonunique Clustered Index           |                                     |
| Unique NCI on a heap                | Yes                                 |
| Non Unique NCI on a heap            |                                     |
| Unique NCI on a clustered index     | Yes                                 |
| Non Unique NCI on a clustered index | Yes                                 |
+-------------------------------------+-------------------------------------+
最后一个问题需要解释一下。在本答案开头的表变量定义中,
Name
上的非唯一非聚集索引由
Name,Id
上的唯一索引模拟(请记住,SQL Server无论如何都会将聚集索引键添加到非唯一NCI键)

非唯一聚集索引也可以通过手动添加
IDENTITY
列作为唯一化器来实现

DECLARE @T TABLE
(
A INT NULL,
B INT NULL,
C INT NULL,
Uniqueifier INT NOT NULL IDENTITY(1,1),
UNIQUE CLUSTERED (A,Uniqueifier)
)

但这并不能准确模拟非唯一聚集索引在SQL Server中的实际实现方式,因为这会向所有行添加“唯一性”。不仅仅是那些需要它的人。

应该理解,从性能的角度来看,@temp表和支持变量的#temp表之间没有区别。它们位于同一个位置(tempdb),并以相同的方式实现。所有差异都出现在附加功能中。请看这篇惊人完整的文章:

尽管在某些情况下不能使用临时表,例如在表或标量函数中,但对于v2016之前的大多数其他情况(甚至可以将过滤后的索引添加到表变量中),您只需使用#临时表即可

在tempdb中使用命名索引(或约束)的缺点是名称可能会冲突。不仅在理论上,对于其他过程,而且对于过程本身的其他实例,通常非常容易,这些实例将尝试在其#temp表的副本上放置相同的索引

为避免名称冲突,通常可以采用以下方法:

declare @cmd varchar(500)='CREATE NONCLUSTERED INDEX [ix_temp'+cast(newid() as varchar(40))+'] ON #temp (NonUniqueIndexNeeded);';
exec (@cmd);

这确保了名称始终是唯一的,即使在同一过程的同时执行之间也是如此。

如果表变量具有大数据,则代替表变量(@Table)创建临时表(#Table)。表变量不允许在插入后创建索引

 CREATE TABLE #Table(C1 int,       
  C2 NVarchar(100) , C3 varchar(100)
  UNIQUE CLUSTERED (c1) 
 ); 
  • 创建具有唯一聚集索引的表

  • 将数据插入临时“#表”表

  • 创建非聚集索引

     CREATE NONCLUSTERED INDEX IX1  ON #Table (C2,C3);
    

  • 创建这两种临时表都有成本;如果你有这么多的数据,你需要一个索引,也许是时候看看使用一个真正的表;您设置为交易安全;按spid或用户id进行筛选,然后在末尾将其清除。Real tables和temp tables都有它们的起伏,但如果性能是一个问题;用一张真正的桌子也可以试试。临时桌子是一张真正的桌子,当你完成后它就消失了。真正的区别(除了它会自动消失)是它在TempDB中。当涉及到索引和约束时,这实际上是一个巨大的问题,因为最终可能会出现名称冲突,不仅会导致代码的其他执行,还会导致代码在实例中的其他数据库中执行。@bielawski这是一个表变量,而不是临时表。表变量不允许显式命名约束,系统生成的名称保证唯一。他们确实允许从2014年开始命名索引,但这不是问题,因为索引只需要在对象内唯一命名,而不需要跨对象命名。我的观点是2倍。1) 除了使用变量来避免事务纠缠之外,临时表和表变量之间没有实质性的区别。然而在V-2000中
     CREATE TABLE #Table(C1 int,       
      C2 NVarchar(100) , C3 varchar(100)
      UNIQUE CLUSTERED (c1) 
     ); 
    
     CREATE NONCLUSTERED INDEX IX1  ON #Table (C2,C3);