Sql 在表变量上创建索引
能否在SQL Server 2000中为表变量创建索引 i、 eSql 在表变量上创建索引,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,但为了方便使用最新版本的开发人员,我将首先解决这个问题
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);