Symptomy
W przypadku używania funkcji SCOPE_IDENTITY() lub @@IDENTITYw celu pobrania wartości wstawionych do kolumny tożsamości można zauważyć, że te funkcje czasami zwracają nieprawidłowe wartości. Ten problem występuje tylko wtedy, gdy zapytania korzystają z planów wykonywania równoległego. Aby uzyskać więcej informacji na temat określania, czy zapytania mają korzystać z planów wykonywania równoległego, zobacz sekcję Równoległość zapytań intra-query w następującym artykule technicznym w artykule Materiały do pobrania firmy Microsoft:
Przyczyna
Firma Microsoft potwierdziła, że jest to usterka występująca w produktach firmy Microsoft wymienionych na początku tego artykułu.
Rozwiązanie
Informacje o aktualizacji skumulowanej
SQL Server 2008 R2 z dodatkiem Service Pack 1
Poprawkę dla tego problemu opublikowano po raz pierwszy w aktualizacji skumulowanej 5 dla programu SQL Server 2008 R2 z dodatkiem Service Pack 1. Aby uzyskać więcej informacji na temat sposobu uzyskania tego pakietu aktualizacji skumulowanej, kliknij następujący numer artykułu, aby wyświetlić ten artykuł w bazie wiedzy Microsoft Knowledge Base:
2659694Pakiet aktualizacji skumulowanej 5 dla programu SQL Server 2008 R2 z dodatkiem Service Pack 1
UwagaPonieważ kompilacje są skumulowane, każda nowa wersja poprawki zawiera wszystkie poprawki i wszystkie poprawki zabezpieczeń, które zostały uwzględnione w poprzedniej wersji poprawki programu SQL Server 2008 R2. Zalecamy rozważenie zastosowania najnowszej poprawki zawierającej tę poprawkę. Aby uzyskać więcej informacji, kliknij następujący numer artykułu w celu wyświetlenia tego artykułu z bazy wiedzy Microsoft Knowledge Base:
2567616Kompilacje programu SQL Server 2008 R2 wydane po zwolnieniu programu SQL Server 2008 R2 z dodatkiem Service Pack 1
Obejście
Firma Microsoft zaleca, aby nie używać tych funkcji w zapytaniach, jeśli w przypadku korzystania z planów równoległych nie zawsze są one niezawodne. Zamiast tego użyj klauzuli OUTPUT instrukcji INSERT, aby pobrać wartość tożsamości, jak pokazano w poniższym przykładzie.
Przykład użycia klauzuli OUTPUT:
DECLARE @MyNewIdentityValues tabela(myidvalues int)
deklarowanie @A tabeli (id int klucza podstawowego)
wstawianie do @A (1)
zadeklaruj @B tabeli (id int tożsamości klucza podstawowego(1;1), B int not null)
wstawianie do @B (1)
wybierz pozycję
[Liczba Wierszy] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE_IDENTITY] = SCOPE_IDENTITY()
ustaw profil statystyki w dniu
wstawianie do _ddr_T
dane inserted.ID do @MyNewIdentityValues
wybierz pozycję
b.ID
z @A a
Left join @B b on b.ID = 1
lewe dołączenie @B b2 w b2. B = -1
left join _ddr_T t on t.T = -1
gdzie nie istnieje (wybierz * z _ddr_T t2, gdzie t2.ID = -1)
ustawianie wyłączonego profilu statystyki
wybierz pozycję
[Liczba Wierszy] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE_IDENTITY] = SCOPE_IDENTITY(),
[IDENT_CURRENT] = IDENT_CURRENT('_ddr_T')
wybierz * w @MyNewIdentityValues
przejdź
Jeśli w Twojej sytuacji konieczne jest użycie jednej z tych funkcji, możesz obejść ten problem za pomocą jednej z poniższych metod.
Metoda 1.
Uwzględnij w zapytaniu następującą opcję
OPCJA (MAXDOP 1)
Uwaga:Może to zaszkodzić wydajności części zapytania SELECT.
Metoda 2.
Odczytaj wartość z części SELECT do zestawu zmiennych (lub jednej zmiennej tabeli), a następnie wstaw do tabeli docelowej za pomocą maxdop=1. Ponieważ plan INSERT nie będzie równoległy, otrzymasz właściwą semantykę, ale wybór SELECT będzie równoległy, aby osiągnąć żądaną wydajność.
Metoda 3:
Uruchom następującą instrukcje, aby ustawić maksymalny stopień równoległości na wartość 1:
sp_configure "maksymalny stopień równoległości", 1
przejdź
ponowne konfigurowanie za pomocą zastępowania
przejdź
Uwaga:ta metoda może spowodować obniżenie wydajności serwera. Tej metody nie należy używać, chyba że została ona oszacowana w środowisku testowania lub tymczasowego.