Chcę wstawić dane do mojej tabeli, ale wstaw tylko te dane, które jeszcze nie istnieją w mojej bazie danych.
Oto mój kod:
ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
(@_DE nvarchar(50),
@_ASSUNTO nvarchar(50),
@_DATA nvarchar(30) )
AS
BEGIN
INSERT INTO EmailsRecebidos (De, Assunto, Data)
VALUES (@_DE, @_ASSUNTO, @_DATA)
WHERE NOT EXISTS ( SELECT * FROM EmailsRecebidos
WHERE De = @_DE
AND Assunto = @_ASSUNTO
AND Data = @_DATA);
END
Błąd to:
Msg 156, poziom 15, stan 1, e-maile z procedurami RecebidosInsert, wiersz 11
Niepoprawna składnia w pobliżu słowa kluczowego „GDZIE”.
sql
sql-server
sql-server-2008
stored-procedures
Francisco Carvalho
źródło
źródło
insert
wyciąg jest zawsze pojedynczą transakcją. To nie tak, że SQL Server najpierw ocenia podkwerendę, a następnie w pewnym momencie i bez przytrzymywania blokady kontynuuje wstawianie.Odpowiedzi:
zamiast poniżej kodu
zamienić
Zaktualizowano: (dzięki @Marc Durdin za wskazanie)
Zauważ, że przy dużym obciążeniu czasami to się nie powiedzie, ponieważ drugie połączenie może przejść test IF NOT EXISTS, zanim pierwsze połączenie wykona INSERT, tj. Warunek wyścigu. Zobacz stackoverflow.com/a/3791506/1836776, aby uzyskać dobrą odpowiedź na pytanie, dlaczego nawet zawarcie transakcji nie rozwiązuje tego problemu.
źródło
select *
w tym przypadku nie robi żadnej różnicy, ponieważ jest używany wEXISTS
klauzuli. SQL Server zawsze go optymalizuje i robi to od wieków. Ponieważ jestem bardzo stary, zwykle piszę te zapytania,EXISTS (SELECT 1 FROM...)
ale nie są one już potrzebne.Dla tych, którzy szukają najszybszego sposobu , ostatnio natknąłem się na te testy porównawcze, w których najwyraźniej użycie „INSERT SELECT ... EXCEPT SELECT ...” okazało się najszybsze dla 50 milionów rekordów lub więcej.
Oto przykładowy kod z artykułu (trzeci blok kodu był najszybszy):
źródło
Użyłbym scalenia:
źródło
Wypróbuj poniższy kod
źródło
INSERT
Komenda nie posiadaWHERE
klauzuli - musisz napisać to tak:źródło
Zrobiłem to samo z SQL Server 2012 i zadziałało
źródło
W zależności od wersji (2012?) Programu SQL Server oprócz IF EXISTS można również użyć funkcji MERGE w następujący sposób:
źródło
Inny SQL, ta sama zasada. Wstaw tylko, jeśli klauzula, w której nie istnieje, zawiedzie
źródło
Jak wyjaśniono w poniższym kodzie: Wykonaj poniższe zapytania i zweryfikuj siebie.
Wstaw rekord:
Teraz spróbuj ponownie wstawić ten sam rekord:
Wstaw inny rekord:
źródło
Możesz użyć
GO
polecenia. Spowoduje to ponowne uruchomienie wykonywania instrukcji SQL po wystąpieniu błędu. W moim przypadku mam kilka 1000 instrukcji INSERT, w których garść tych rekordów już istnieje w bazie danych, po prostu nie wiem, które z nich. Odkryłem, że po przetworzeniu kilku 100 wykonanie kończy się z komunikatem o błędzie, że nie może,INSERT
ponieważ rekord już istnieje. Dość denerwujące, aleGO
rozwiązanie tego. To może nie być najszybsze rozwiązanie, ale prędkość nie była moim problemem.źródło
GO
jest separatorem wsadowym? Nie pomaga w zapobieganiu powielaniu rekordów.