Czy można utworzyć indeks dla zmiennej tabeli w SQL Server 2000?
to znaczy
DECLARE @TEMPTABLE TABLE (
[ID] [int] NOT NULL PRIMARY KEY
,[Name] [nvarchar] (255) COLLATE DATABASE_DEFAULT NULL
)
Czy mogę utworzyć indeks na Name
?
sql
sql-server
tsql
indexing
table-variable
GordyII
źródło
źródło
CREATE TABLE #T1(X INT); CREATE TABLE #T2(X INT); CREATE INDEX IX ON #T1(X); CREATE INDEX IX ON #T2(X);
Odpowiedzi:
Pytanie jest oznaczone jako SQL Server 2000, ale najpierw rozwiążę tę kwestię z korzyścią dla osób rozwijających najnowszą wersję.
SQL Server 2014
Oprócz metod dodawania indeksów opartych na ograniczeniach omówionych poniżej SQL Server 2014 umożliwia także bezpośrednie określanie indeksów nie unikatowych za pomocą wbudowanej składni deklaracji zmiennych tabeli.
Przykładowa składnia tego jest poniżej.
Filtrowanych indeksów i indeksów z dołączonymi kolumnami nie można obecnie zadeklarować za pomocą tej składni, jednak SQL Server 2016 nieco to rozluźnia. Od CTP 3.1 można teraz deklarować przefiltrowane indeksy dla zmiennych tabeli. Według RTM może się zdarzyć, że uwzględnione kolumny są również dozwolone, ale obecna pozycja jest taka, że „prawdopodobnie nie dostaną się do SQL16 z powodu ograniczeń zasobów”
SQL Server 2000 - 2012
Krótka odpowiedź: tak.
Bardziej szczegółowa odpowiedź znajduje się poniżej.
Tradycyjne tabele w SQL Server mogą mieć indeks klastrowany lub mają strukturę stosów .
Indeksy klastrowe można zadeklarować jako unikalne, aby uniemożliwić powielanie wartości kluczy, lub domyślnie jako niepowtarzalne. Jeśli nie jest unikalny, to SQL Server cicho dodaje unikatowy do każdego zduplikowanego klucza, aby były unikalne.
Indeksy nieklastrowane można również jawnie zadeklarować jako unikalne. W przeciwnym razie w przypadku nie unikatowego przypadku SQL Server dodaje lokalizator wierszy (klastrowany klucz indeksu lub RID dla sterty) do wszystkich kluczy indeksu (nie tylko duplikatów), co ponownie zapewnia ich unikalność.
W SQL Server 2000 - 2012 indeksy zmiennych tabeli można tworzyć niejawnie tylko przez utworzenie ograniczenia
UNIQUE
lubPRIMARY KEY
. Różnica między tymi typami ograniczeń polega na tym, że klucz podstawowy musi znajdować się w kolumnach, które nie mają wartości NULL. Kolumny uczestniczące w unikalnym ograniczeniu mogą mieć wartość null. (chociaż implementacja unikalnych ograniczeń przez SQL Server w obecnościNULL
s nie jest zgodna ze specyfikacją SQL Standard). Również tabela może mieć tylko jeden klucz podstawowy, ale wiele unikalnych ograniczeń.Oba te ograniczenia logiczne są fizycznie realizowane za pomocą unikalnego indeksu. Jeśli nie zostanie to wyraźnie określone inaczej,
PRIMARY KEY
stanie się indeksem klastrowanym i unikatowymi ograniczeniami nieklastrowanymi, ale to zachowanie można zastąpić poprzez określenieCLUSTERED
lubNONCLUSTERED
jawnie za pomocą deklaracji ograniczeń (przykładowa składnia)W wyniku powyższego można domyślnie utworzyć następujące indeksy na zmiennych tabeli w SQL Server 2000 - 2012.
Ten ostatni wymaga trochę wyjaśnienia. W definicji zmiennej tabeli na początku tej odpowiedzi symulowany jest nie unikalny indeks nieklastrowany
Name
przez unikalny indeks włączonyName,Id
(pamiętaj, że SQL Server i tak po cichu dodałby klastrowany klucz indeksu do nie unikatowego klucza NCI).IDENTITY
Niejednoznaczny indeks klastrowy można również uzyskać ręcznie dodając kolumnę, która będzie działać jako unikatator.Ale nie jest to dokładna symulacja tego, jak normalnie klaster klastrowy normalnie zostałby faktycznie zaimplementowany w SQL Server, ponieważ dodaje to „Uniqueifier” do wszystkich wierszy. Nie tylko ci, którzy tego wymagają.
źródło
Należy rozumieć, że z punktu widzenia wydajności nie ma różnic między tabelami @temp a tabelami #temp, które faworyzują zmienne. Znajdują się w tym samym miejscu (tempdb) i są wdrażane w ten sam sposób. Wszystkie różnice pojawiają się w dodatkowych funkcjach. Zobacz ten niezwykle kompletny opis: /dba/16385/whats-the-difference-between-a-temp-table-and-table-variable-in-sql-server/16386#16386
Chociaż istnieją przypadki, w których nie można użyć tabeli tymczasowej, takie jak funkcje tabelowe lub skalarne, w większości innych przypadków przed wersją v2016 (gdzie nawet zmienne indeksy można dodać do zmiennej tabeli), można po prostu użyć tabeli #temp.
Wadą używania indeksów nazwanych (lub ograniczeń) w tempdb jest to, że nazwy mogą się następnie kolidować. Nie tylko teoretycznie z innymi procedurami, ale często dość łatwo z innymi instancjami samej procedury, które próbowałyby umieścić ten sam indeks na swojej kopii tabeli #temp.
Aby uniknąć konfliktów nazw, zwykle działa coś takiego:
Zapewnia to, że nazwa jest zawsze unikalna, nawet między jednoczesnymi wykonywaniem tej samej procedury.
źródło
Jeśli zmienna tabeli ma duże dane, zamiast zmiennej tabeli (@table) utwórz tabelę temp (#table). Zmienna table nie pozwala na utworzenie indeksu po wstawieniu.
Utwórz tabelę z unikalnym indeksem klastrowym
Wstaw dane do tabeli Temp „#Table”
Utwórz indeksy klastrowe.
źródło