2009-05-20 33 views
130

Bạn có thể tạo chỉ mục trên biến bảng trong SQL Server 2000 không?Tạo chỉ mục trên biến bảng

ví dụ:

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

Tôi có thể tạo một chỉ mục trên danh?

+3

Có chi phí trong việc tạo cả hai loại bảng tạm thời; và nếu bạn có quá nhiều dữ liệu trong đó bạn cần một chỉ mục, đó có thể là thời gian để xem xét bằng cách sử dụng một bảng thực; mà bạn thiết lập để giao dịch an toàn; lọc theo spid hoặc id người dùng và sau đó xóa nó ở cuối. Các bảng v bảng tạm thời thực sự đều có những thăng trầm nhưng nếu hiệu suất là một vấn đề; thử nó với một cái bàn thật. – u07ch

+0

Một bảng tạm thời 'IS' là một bảng thực, nó chỉ biến mất khi bạn hoàn thành. Sự khác biệt thực sự (khác với nó sẽ tự động biến mất) là nó ở trong TempDB. Điều này thực sự rất lớn khi nói đến các chỉ mục và các ràng buộc bởi vì bạn có thể kết thúc với các xung đột tên, không chỉ với các đoạn mã lệnh khác mà còn với việc thực thi mã trong các cơ sở dữ liệu khác trong cá thể của bạn. – bielawski

+0

@bielawski đây là biến bảng không phải là bảng tạm thời. Các biến bảng không cho phép các ràng buộc được đặt tên rõ ràng, tên được tạo bởi hệ thống được đảm bảo là duy nhất.Chúng cho phép các chỉ mục được đặt tên từ năm 2014 nhưng đó không phải là vấn đề vì chỉ mục chỉ cần được đặt tên duy nhất trong một đối tượng không phải trên các đối tượng. –

Trả lời

256

Câu hỏi được gắn thẻ SQL Server 2000 nhưng vì lợi ích của những người phát triển trên phiên bản mới nhất, tôi sẽ giải quyết điều đó trước tiên.

SQL Server 2014

Ngoài các phương pháp bổ sung danh mục hạn chế dựa trên thảo luận dưới đây SQL Server 2014 cũng cho phép chỉ số phi duy nhất để được chỉ định trực tiếp với cú pháp nội tuyến trên tờ khai biến bảng.

Ví dụ về cú pháp dưới đây.

/*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*/ 
); 

chỉ số lọc và lập chỉ mục với các cột bao gồm thể hiện không được khai báo với cú pháp này tuy nhiên SQL Server 2016 thư giãn này một chút nữa. Từ CTP 3.1, bây giờ có thể khai báo các chỉ mục đã lọc cho các biến bảng. Bởi RTM nó thể là trường hợp đó bao gồm các cột cũng được phép nhưng vị trí hiện tại là họ "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 - 2012

Tôi có thể tạo một chỉ mục trên Tên?

Câu trả lời ngắn gọn: Có.

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

Câu trả lời chi tiết hơn bên dưới.

Bảng truyền thống trong SQL Server có thể có chỉ mục nhóm hoặc được cấu trúc là heaps.

Chỉ mục được nhóm có thể được khai báo là duy nhất để không cho phép các giá trị khóa trùng lặp hoặc mặc định thành không duy nhất. Nếu không phải là duy nhất thì SQL Server sẽ tự động thêm uniqueifier vào bất kỳ khóa trùng lặp nào để làm cho chúng trở thành duy nhất.

Chỉ mục không được nhóm cũng có thể được khai báo rõ ràng là duy nhất. Nếu không cho trường hợp không duy nhất SQL Server adds the row locator (phím chỉ mục nhóm hoặc RID cho một đống) cho tất cả các phím chỉ mục (không chỉ trùng lặp), điều này một lần nữa đảm bảo chúng là duy nhất.

Trong SQL Server 2000 - 2012 chỉ mục trên các biến bảng chỉ có thể được tạo ngầm bằng cách tạo ra ràng buộc UNIQUE hoặc PRIMARY KEY. Sự khác biệt giữa các kiểu ràng buộc này là khóa chính phải nằm trên các cột không có giá trị rỗng. Các cột tham gia vào một ràng buộc duy nhất có thể là nullable. (mặc dù việc thực thi SQL Server của các ràng buộc duy nhất trong sự hiện diện của NULL s không phải là theo quy định trong tiêu chuẩn SQL). Ngoài ra một bảng chỉ có thể có một khóa chính nhưng nhiều ràng buộc duy nhất.

Cả hai ràng buộc logic này được triển khai thực tế với chỉ mục duy nhất. Nếu không xác định rõ ràng nếu không PRIMARY KEY sẽ trở thành chỉ số clustered và ràng buộc duy nhất không cụm nhưng hành vi này có thể được ghi đè bằng cách xác định CLUSTERED hoặc NONCLUSTERED một cách rõ ràng với việc kê khai chế (Ví dụ cú pháp)

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

Như một kết quả của các bên trên các chỉ mục sau có thể được tạo ngầm định trên các biến bảng trong SQL Server 2000 - 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         | 
+-------------------------------------+-------------------------------------+ 

Điều cuối cùng yêu cầu một chút giải thích. Trong định nghĩa biến bảng ở đầu câu trả lời này, chỉ số không độc nhất không được nhóm trên Name được mô phỏng bằng một chỉ số duy nhất trên Name,Id (nhớ lại rằng SQL Server sẽ tự động thêm khóa chỉ mục nhóm vào khóa NCI không duy nhất).

Một chỉ mục nhóm không độc đáo cũng có thể đạt được bằng cách thêm một cột IDENTITY theo cách thủ công để hoạt động như một bộ duy nhất.

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

Nhưng đây không phải là mô phỏng chính xác về cách một chỉ mục nhóm không thực hiện bình thường thực sự được triển khai trong SQL Server vì điều này thêm "Uniqueifier" vào tất cả các hàng. Không chỉ những người yêu cầu nó.

+1

Lưu ý: Giải pháp 2000-2012 chỉ hoạt động nếu cột văn bản <= 900 byte. I E. varchar (900), nvarchar (450) –

+1

@AndreFigueiredo yep, đó cũng là kích thước tối đa cho khóa chỉ mục trên bảng vĩnh viễn trong các phiên bản đó. –

+0

Tôi chỉ muốn lưu ý rằng câu trả lời SQL 2014 hoạt động tốt trong Azure. Cảm ơn Martin! – Jaxidian

11

Cần hiểu rằng từ quan điểm hiệu suất không có sự khác biệt giữa bảng @temp và bảng #temp có lợi cho các biến. Họ cư trú ở cùng một nơi (tempdb) và được thực hiện theo cùng một cách. Tất cả sự khác biệt xuất hiện trong các tính năng bổ sung. Hãy xem bài viết hoàn chỉnh này: https://dba.stackexchange.com/questions/16385/whats-the-difference-between-a-temp-table-and-table-variable-in-sql-server/16386#16386

Mặc dù có trường hợp bảng tạm thời không thể được sử dụng như trong bảng hoặc chức năng vô hướng, cho hầu hết các trường hợp khác trước v2016 (trong đó có thể thêm chỉ mục đã lọc vào bảng) biến) bạn chỉ có thể sử dụng bảng #temp.

Hạn chế sử dụng các chỉ mục có tên (hoặc các ràng buộc) trong tempdb là các tên có thể sau đó xung đột. Không chỉ về mặt lý thuyết với các thủ tục khác mà thường khá dễ dàng với các trường hợp khác của thủ tục mà sẽ cố gắng đặt cùng một chỉ mục trên bản sao của bảng #temp.

Để tránh xung đột tên, một cái gì đó như thế này thường hoạt động:

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

Điều này đảm bảo tên phải lúc nào cũng độc đáo thậm chí giữa hành đồng thời các thủ tục tương tự.

+0

Nó có một khung bị thiếu sau varchar (40), thêm rằng –

+0

Không có vấn đề với chỉ mục được đặt tên - chỉ mục chỉ phải được đặt tên duy nhất trong một bảng. Vấn đề là với các ràng buộc có tên và giải pháp tốt nhất nói chung là không đặt tên chúng trong các bảng tạm thời - các ràng buộc có tên ngăn chặn tạm thời đối tượng bảng tạm thời. –

+0

Điều đó chỉ đúng đối với một số phiên bản nhất định (nếu đúng với bất kỳ phiên bản nào). Tôi đã phải đưa ra cách giải quyết này đặc biệt bởi vì tôi truy tìm lỗi sp để đụng độ của các chỉ mục có tên trong quá trình thực hiện đồng thời. – bielawski

Các vấn đề liên quan