Załóżmy, że posiadamy dwie tabelki posiadające te same pola. Dla uproszczenia o to kod do ich stworzenia:
CREATE TABLE #TEST1 ([ID] INT,[IDN] VARCHAR(200)) INSERT INTO #TEST1 VALUES (1,'Jeden') INSERT INTO #TEST1 VALUES (2,'Dwa') INSERT INTO #TEST1 VALUES (3,'Trzy') INSERT INTO #TEST1 VALUES (4,'Cztery') INSERT INTO #TEST1 VALUES (5,'Pięć') INSERT INTO #TEST1 VALUES (6,'Sześć') INSERT INTO #TEST1 VALUES (7,'Siedem') INSERT INTO #TEST1 VALUES (8,'Osiem') INSERT INTO #TEST1 VALUES (9,'Dziewięć') INSERT INTO #TEST1 VALUES (10,'Dziesięć') CREATE TABLE #TEST2 ([ID] INT,[IDN] VARCHAR(200)) INSERT INTO #TEST2 VALUES (3,'Trzy') SELECT * FROM #TEST1 SELECT * FROM #TEST2
Powiedzmy, że teraz z tabelki #TEST1 chcemy usunąć te wartości, które znajdują się także w tabeli #TEST2. Wykonujemy więc bardzo prosty kawałek kodu:
DELETE FROM #TEST1 WHERE [IDN] IN (SELECT [IDN] FROM #TEST2)
Po usunięciu sprawdzamy co zostało nam w tabeli #TEST1:
SELECT * FROM #TEST1
Wynik jest taki jak chcieliśmy nie ma rekordu z wartością 3. Załóżmy, że jakiś nieznany osobnik skasował w naszej tabeli #TEST2 kolumnę [IDN] i ponownie dodał wartość 3 do tabeli #TEST1
ALTER TABLE #TEST2 DROP COLUMN [IDN] INSERT INTO #TEST1 VALUES (3,'Trzy')
Ponieważ w naszej tabeli #TEST1 ponownie pojawiła się wartość 3 chcemy ją znów usunąć. Ponieważ nie wiemy, że nasz złoczyńca skasował kolumnę [IDN] wykonujemy polecenie kasujące, z którego korzystaliśmy poprzednio. Zapewne część z was spodziewa się tego, że wynikiem takiego kasowania będzie błąd ponieważ nie ma już kolumny [IDN] w tabeli #TEST2..
Jeżeli wykonaliście już kod wiecie, że niestety nic takiego się nie stanie. Zamiast tego z tabeli #TEST1 zostaną skasowane wszystkie wpisy! Jeżeli zadajecie sobie pytanie „ALE DLACZEGO !!” odpowiedź jest bardzo prosta. Ponieważ SQL Server nie znalazł w tabeli #TEST2 kolumny [IDN] założył, że należy znaleźć inną kolumnę [IDN] i znalazł ją w tabeli #TEST1 co spowodowało że zapytanie kasujące było zinterpretowane tak samo jak następujące zapytanie:
DELETE FROM #TEST1 WHERE [IDN] IN [IDN]
Co oczywiście skasuje wszystkie wpisy w tabeli #TEST1. Jak uniknąć takich sytuacji ? Korzystaj z aliasów lub pełnych nazw w takich przypadkach. Wystarczy aby nasze zapytanie kasujące było zbudowane w następujący sposób:
DELETE FROM #TEST1 WHERE [IDN] IN (SELECT T2.[IDN] FROM #TEST2 T2)
Po wywołaniu tego zapytania zamiast skasować cokolwiek w tabeli #TEST1 dostaniemy następujący błąd:
Msg 207, Level 16, State 1, Line 1
Invalid column name ‘IDN’.
Co w założonej sytuacji jest jak najbardziej poprawne.