Mieć unikalne wartości w nieunikalnej nicości
Załóżmy, że posiadamy tabelę, która może być w relacji jeden do jednego do innej tabeli lub tej relacji nie posiadać. Przykładem może być np. tabela kierowców firmy transportowej. Do jednego kierowcy może być przyporządkowany tylko jeden pojazd lub kierowca może obecnie nie być w trasie i wówczas brak przyporządkowania (co oznacza, że w tabeli w kolumnie wiążącej nie ma wartości klucza obcego – jest null – nicość 😉 ).
Dobrze byłoby narzucić odpowiednie ograniczenia na tego typu tabelę, czyli zabezpieczyć przed możliwością przyporządkowania do dwóch wierszy tego samego wiersza z tabeli przyporządkowywanej. Najbardziej oczywistym rozwiązaniem wydaje się być narzucenie kolumnie reguły unikalności przechowywanych wartości. Rzecz w tym, że jednocześnie oczekujemy, że kolumna ta w szczególności nie będzie unikalna (część wierszy może nie mieć powiązania – powtórzy się wartość null). Jak wiadomo indeks unikalny dopuszcza wartość null … no właśnie wartość, a nie wartości.
Czy w takim razie najbardziej oczywiste i najwygodniejsze rozwiązanie będzie nieosiągalne? Otóż nie (na szczęście)! Począwszy od wersji 2008 Serwera SQL indeksy mogą posiadać wyrażenie filtrujące (osiągane za pomocą klauzuli where). Zamiast więc tworzyć indeks następująco:
create unique index [UnikalnaKolumnaWiążąca] on [GłównaTabela]([KolumnaWiążąca]);
należy go utworzyć tak:
create unique index [UnikalnaKolumnaWiążąca] on [GłównaTabela]([KolumnaWiążąca]) where [KolumnaWiążąca] is not null;
Od teraz można się cieszyć unikalnymi wartościami w kolumnie, a jednocześnie mieć nieograniczoną (nieunikalną) ilość nicości ;).
Oczywiście rozwiązanie to nie wymaga, aby unikalna kolumna cokolwiek wiązała, może być też tak, że po prostu przechowuje miejsce w kolejce, lokalizację lub cokolwiek co ma być unikalne lub może być puste.