2009-05-20 3 views
130

SQL Server 2000에서 테이블 변수에 인덱스를 만들 수 있습니까?테이블 변수에 인덱스 만들기

DECLARE @TEMPTABLE TABLE (
     [ID] [int] NOT NULL PRIMARY KEY 
     ,[Name] [nvarchar] (255) COLLATE DATABASE_DEFAULT NULL 
) 

나는 이름에 인덱스를 만들 수 즉?

+3

두 종류의 임시 테이블을 만드는 데 비용이 소요됩니다. 그리고 인덱스가 필요하다는 데이터가 너무 많으면 실제 테이블을 사용할 때가 있습니다. 거래 안전을 위해 설정 한 spid 또는 사용자 ID별로 필터링 한 다음 끝에 끝내십시오. 실수 테이블 v 임시 테이블은 성능이 문제가되는 경우에는 둘 다 기복이 있습니다. 진짜 테이블도 함께 시도해보십시오. – u07ch

+0

임시 테이블 'IS'는 실제 테이블이며 완료되면 사라집니다. 실제 차이점은 (자동으로 사라지는 것 외에는) TempDB에 있다는 것입니다. 인덱스와 제약 조건에 대해서는 실제로 엄청나 다. 왜냐하면 코드의 다른 실행뿐만 아니라 인스턴스의 다른 데이터베이스에서 코드가 실행되는 이름 충돌로 끝날 수 있기 때문입니다. – bielawski

+0

@bielawski 이것은 임시 테이블이 아닌 테이블 변수입니다. 테이블 변수는 명시 적으로 명명 된 제약 조건을 허용하지 않으므로 시스템 생성 이름은 고유해야합니다.그들은 2014 년부터 명명 된 인덱스를 허용합니다. 그러나 인덱스는 오브젝트 전체가 아닌 오브젝트 내에서 유일하게 명명되어야하기 때문에 문제가되지 않습니다. –

답변

256

질문에 SQL Server 2000 태그가 지정되었지만 최신 버전으로 개발하는 사람들을 위해 먼저 해결할 것입니다.

SQL 서버 2014 후술 제약 기반 인덱스를 추가하는 방법 외에 2,014

SQL 서버는 비 고유 인덱스 테이블 변수 선언 인라인 구문을 직접 지정할 수있다.

구문의 예는 다음과 같습니다. 포함 된 열

/*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 서버 2016로 선언 할 수없는 것은 조금 더이 이완한다. CTP 3.1부터 테이블 변수에 대해 필터링 된 인덱스를 선언 할 수 있습니다.

2012 난을 만들 수 - RTM으로는 컬럼도 허용되지만 현재 위치가 그들이 "will likely not make it into SQL16 due to resource constraints"

/*SQL Server 2016 allows filtered indexes*/ 
DECLARE @T TABLE 
(
c1 INT NULL INDEX ix UNIQUE WHERE c1 IS NOT NULL /*Unique ignoring nulls*/ 
) 

SQL Server 2000에 있다는 것입니다 포함 된 경우 일 수 이름에 대한 색인?

짧은 대답 : 예.

DECLARE @TEMPTABLE TABLE (
    [ID] [INT] NOT NULL PRIMARY KEY, 
    [Name] [NVARCHAR] (255) COLLATE DATABASE_DEFAULT NULL, 
    UNIQUE NONCLUSTERED ([Name], [ID]) 
) 

자세한 대답은 아래에 있습니다.

SQL Server의 기존 테이블은 클러스터 된 인덱스를 갖거나 heaps으로 구조화 될 수 있습니다.

클러스터 된 인덱스는 중복 키 값을 허용하지 않으려면 고유 한 것으로 선언하거나 비 고유로 기본값을 선언 할 수 있습니다. 고유하지 않으면 SQL Server는 중복 키에 자동으로 uniqueifier을 추가하여 고유하게 만듭니다.

클러스터되지 않은 인덱스도 고유하게 명시 적으로 선언 할 수 있습니다. 그렇지 않으면 고유하지 않은 모든 SQL Server adds the row locator (클러스터 된 인덱스 키 또는 힙의 경우 RID)을 모든 인덱스 키 (중복이 아님)에 다시 지정하면 고유 한 값이됩니다.

SQL Server 2000 - 2012에서 테이블 변수의 인덱스는 UNIQUE 또는 PRIMARY KEY 제약 조건을 만들어 암시 적으로 만 만들 수 있습니다. 이러한 제약 조건 유형의 차이점은 기본 키가 null이 아닌 열 (들)에 있어야한다는 것입니다. 고유 제한 조건에 참여하는 컬럼은 널 (NULL) 입력 가능할 수 있습니다. (NULL이있는 상태에서 SQL Server의 고유 제약 조건 구현은 SQL 표준에 지정된 제약 조건이 아님). 또한 테이블에는 기본 키가 하나만있을 수 있지만 고유 한 제약 조건이 여러 개 있습니다.

이러한 논리 제약 조건은 물리적으로 고유 한 인덱스로 구현됩니다. 명시 적으로 지정되지 않은 경우 PRIMARY KEY는 클러스터 된 인덱스가 될 것이며, 고유 제한 조건은 클러스터되지 않은 그러나이 동작은 위의 결과로 제약 선언으로 명시 적으로 (예 구문)

DECLARE @T TABLE 
(
A INT NULL UNIQUE CLUSTERED, 
B INT NOT NULL PRIMARY KEY NONCLUSTERED 
) 

CLUSTERED 또는 NONCLUSTERED를 지정하여 대체 할 수 있습니다 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         | 
+-------------------------------------+-------------------------------------+ 

마지막 약간의 설명이 필요 - 다음 인덱스는 암시 2000은 SQL Server의 테이블 변수를 만들 수 있습니다. 이것의 시작 부분에 테이블 변수 정의에서 Name,Id독특한 인덱스 시뮬레이션 Name비 독특한 비 클러스터형 인덱스 대답 (자동 어쨌든 비 독특한 NCI 키에 클러스터 된 인덱스 키를 추가하는 SQL 서버를 리콜).

고유하지 않은 클러스터 된 인덱스는 IDENTITY 열을 수동으로 추가하여 고유 식별자 역할을 수행 할 수도 있습니다.

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

는하지만이 모든 행에 "uniqueifier를"을 추가로 비 고유 클러스터형 인덱스는 일반적으로 실제로 SQL 서버에서 구현 될 것입니다 방법에 대한 정확한 시뮬레이션이 아니다. 뿐만 아니라 그것을 필요로하는 사람들.

+1

참고 : 2000-2012 솔루션은 텍스트 열 <= 900 바이트 인 경우에만 작동합니다. 즉. varchar (900), nvarchar (450) –

+1

@AndreFigueiredo 예, 해당 버전의 영구 테이블에도 인덱스 키의 최대 크기입니다. –

+0

저는 SQL 2014 대답이 Azure에서 잘 작동한다는 것을 알고 싶었습니다. Martin 고마워! – Jaxidian

11

성능 측면에서 변수를 선호하는 @temp 테이블과 #temp 테이블간에 차이가 없음을 이해해야합니다. 이들은 같은 장소 (tempdb)에 상주하며 동일한 방식으로 구현됩니다. 모든 차이점이 추가 기능에 나타납니다. https://dba.stackexchange.com/questions/16385/whats-the-difference-between-a-temp-table-and-table-variable-in-sql-server/16386#16386

테이블 또는 스칼라 함수와 같이 임시 테이블을 사용할 수없는 경우가 있지만 v2016 이전의 대부분의 경우 (필터링 된 인덱스조차도 테이블에 추가 할 수있는 경우도 있음) 변수)를 사용하면 간단히 #temp 테이블을 사용할 수 있습니다.

tempdb에서 명명 된 인덱스 (또는 제약 조건)를 사용하면 단점은 이름이 충돌 할 수 있다는 것입니다. 이론적으로는 다른 프로 시저를 사용하는 것뿐만 아니라 #temp 테이블의 복사본에 동일한 인덱스를 넣으려고하는 다른 프로 시저 인스턴스를 사용하는 경우도 있습니다.

이름 충돌을 방지하기 위해이 같은 일반적으로 작동합니다

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

이 이름도 동일한 절차의 동시 실행 사이에 항상 고유 보장한다.

+0

varchar (40) 다음에 괄호가 하나씩없는 경우 추가하십시오. –

+0

명명 된 인덱스에는 문제가 없습니다. 인덱스는 테이블 내에서 고유하게 이름 지정되어야합니다. 문제는 명명 된 제약 조건에 있으며 최적의 솔루션은 일반적으로 임시 테이블에서 이름을 지정하지 않는 것입니다. 명명 된 제약 조건은 임시 테이블 개체 캐싱을 방지합니다. –

+0

특정 버전에만 해당해야합니다 (모든 버전에 해당되는 경우). 동시 실행 중에 이름이 지정된 인덱스의 충돌에 sp 실패를 추적 했으므로 특히이 해결 방법을 찾아야했습니다. – bielawski