INSERT do tabeli z triggerami nie zwraca autoincrementa

0

Witam.
Pracuję na MS SQL Server 2014.
Mam założoną tabelę, na której założone są triggery INSTEAD OF oraz FOR. Gdy wykonuję insert'a do tej tabeli więcej niż jednego rekordu na raz to chciałbym otrzymać autoincrementy dodanych wierszy.
Zazwyczaj robię to tak:

INSERT INTO tabela
(pole1, pole2, poleTmp)
OUTPUT inserted.id, inserted.warTmp INTO #tempIds(idNew, idOld)
SELECT war1, war2, warTmp
FROM ...

Gdzie pole [id] to właśnie autoincrement tabeli.
Niestety po takim insercie pole idNew tabeli #tempIds jest wypełniane zerami. Jeżeli wyłączę triggery to wszystko działa ok. Niestety triggery są mi potrzebne więc nie mogę ich wyłączyć.
Czy jest jakiś sposób aby otrzymać autoincrementy dodanych wierszy.
Potrzebne mi są one do powiazania ich z rekordami źródłowymi (przekazywanymi w polu "poleTmp"). Pojedyncze dodawanie rekordów w pętli nie wchodzi w grę (zależy mi na dużej wydajności, prędkości wykonania zapytania).
Odczytywanie wierszy po dodaniu na podstawie maksymalnego autoincrementa z przed zapytania też nie ma zastosowania gdyż baza będzie pracować na wielu stanowiskach i w jednym czasie może być wykonanych kilka takich insertów z różnych stanowisk.

Czy da się to jakoś rozwiązać nie zabijając zapytania?

0

Na wstępie zaznaczam, że mogę się mylić, ale w moim przekonaniu nie ma fabrycznego rozwiązania dla Twojego problemu. Jak sam zauważyłeś, OUTPUT działa, o ile nie masz triggerów.

Możesz pobrać ostatni ID dodany w tabeli (bez względu na to, kto go dodał):
SELECT IDENT_CURRENT('NAZWA_TABELI')
ostatni dodany w Twoim batchu - czyli ostatnie ID dodane przez Ciebie, lub przez triggery (a więc nie zawsze z tabeli, która Cię interesuje):
SELECT @@IDENTITY
albo ostatni dodany przez Ciebie bezpośrednio, czyli w sumie najbliższy Tobie:
SELECT SCOPE_IDENTITY
Ale... tylko ostatni.
Jeśli chcesz pobrać wszystkie, które ostatnio dodałeś, to musisz szyć.

Luźna propozycja - do tabeli dorzucasz kolumnę typu INT. Tworzysz na tabeli trigger, który uzupełnia tę kolumnę wartością zmiennej @@SPID --identyfikator sesji
Przed insertem pobierasz sobie IDENT_CURRENT(), a po insercie z tabeli wybierasz z tabeli ID-ki od niego większe z dodatkowym warunkiem na własny SPID.

To najprostsze, co przychodzi mi do głowy. Mankament jest taki, że dla każdej tabeli, na której chcesz w ten sposób działać, musisz mieć dodatkową kolumnę i ewentualnie trigger.

Mam nadzieję, że pojawi się ktoś z lepszym rozwiązaniem, bo, nie ukrywam, też jestem ciekaw

1

Bez kodu triggera instead of nie bardzo wiadomo co poradzić.

Przeanalizuj przykład H https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-ver16#examples

0
Panczo napisał(a):

Bez kodu triggera instead of nie bardzo wiadomo co poradzić.

Przeanalizuj przykład H https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-ver16#examples

Po analizie powyższego linku znalazłem rozwiązanie:
W triggerze INSTEAD OF w zapytaniu INSERT dodałem OUTPUT'a do tabeli tymczasowej globalnej, którą zakładam w tym triggerze, oczywiście sprawdzając czy one już istnieje.
Na zewnątrz zapytania odpytuję tą tabelę tymczasową i mam w niej indeksy dodanych rekordów.Oczywiście najpierw tę tabelę należy wyczyścić najlepiej w tym samym triggerze.
Rozwiązanie mało eleganckie ale działa. Dopóki w sql nie pojawi się jakieś dedykowane rozwiązanie można stosować.

0

Z ciekawości, dlaczego masz i instead of na tabeli? W praktyce jeszcze nie spotkałem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1