2012-06-13 14 views
27

Mam tabelę, w której wstawiam wiersze dla pracownika, ale następnym razem, gdy chcę wstawić wiersz, nie chcę wstawiać ponownie danych dla tego pracownika, po prostu chcę zaktualizuj z wymaganymi kolumnami, jeśli zostanie zakończony, jeśli nie, następnie utwórz nowy wierszJak wstawić (zaktualizować lub wstawić) w SQL Server 2005

Jak możemy to zrobić w SQL Server 2005?

używam JSP

moje zapytanie jest

String sql="insert into table1(id,name,itemname,itemcatName,itemQty)values('val1','val2','val3','val4','val5')"; 

jeśli jest to pierwszy raz, a następnie włóż ją do bazy danych innego jeśli występuje zmiana to

jak to zrobić?

+1

Co powiesz na użycie klauzuli ** MERGE ** wraz z tabelą tymczasową z danymi użytkownika? Czy to nie jest lepsze? –

+0

Sakhile - Tak, jest - więc gdzie jest Twoja odpowiedź w sekcji ... odpowiedzi ...? –

+0

"MERGE" byłby odpowiedni dla tego przypadku użycia, ale należy zauważyć, że został wprowadzony tylko w SQL Server 2008 (przypuszczalnie OP nie jest jeszcze używany w 2005 r. Sześć lat później). –

Odpowiedz

32

próby sprawdzenia istnienia:

IF NOT EXISTS (SELECT * FROM dbo.Employee WHERE ID = @SomeID) 

    INSERT INTO dbo.Employee(Col1, ..., ColN) 
    VALUES(Val1, .., ValN) 

ELSE 

    UPDATE dbo.Employee 
    SET Col1 = Val1, Col2 = Val2, ...., ColN = ValN 
    WHERE ID = @SomeID 

Można łatwo owinąć to w procedurze przechowywanej i po prostu nazwać tę procedurę przechowywaną z zewnątrz (na przykład z języka programowania takich jak C# lub cokolwiek używasz) .

Aktualizacja: albo można po prostu napisać całą tę instrukcję w jeden długi ciąg (wykonalne - ale naprawdę nie bardzo przydatne) - czy można owinąć go w procedurze przechowywanej:

CREATE PROCEDURE dbo.InsertOrUdpateEmployee 
     @ID INT, 
     @Name VARCHAR(50), 
     @ItemName VARCHAR(50), 
     @ItemCatName VARCHAR(50), 
     @ItemQty DECIMAL(15,2) 
AS BEGIN 
    IF NOT EXISTS (SELECT * FROM dbo.Table1 WHERE ID = @ID) 
     INSERT INTO dbo.Table1(ID, Name, ItemName, ItemCatName, ItemQty) 
     VALUES(@ID, @Name, @ItemName, @ItemCatName, @ItemQty) 
    ELSE 
     UPDATE dbo.Table1 
     SET Name = @Name, 
      ItemName = @ItemName, 
      ItemCatName = @ItemCatName, 
      ItemQty = @ItemQty 
     WHERE ID = @ID 
END 

a potem po prostu wywołaj tę procedurę przechowywaną z Twojego kodu ADO.NET

+0

gdzie wpisz powyższy kod w powyższym łańcuchu sql lub potrzebujesz utworzyć wyzwalacz lub procedurę. – ybc126

+1

pisanie w jednym ciągu będzie wyglądało jak String sql = "JEŚLI NIE ISTNIEJE (WYBIERZ * OD pracownika WHERE ID = @ someid) WSTAWIĆ W PRACOWNIKÓW (col1, ..., colN) wartości (val1, .., valN) ELSE ZAKTUALIZUJ ZESTAW ZBIORNIKA col1 = val1, col2 = val2, ..., colN = valN WHERE ID = @ someID " Czy to działa. – ybc126

+0

@ ybc126: jeśli masz wymagane spacje w twoim SQL - tak. Ale coś takiego jest ** zdecydowanie ** nie polecane! Wstawienie tego do procedury składowanej (lub użycie ORM do obsłużenia tego) byłoby ** znacznie lepsze ** –

1

Możesz to zrobić za pomocą wyzwalacza INSTEAD OF INSERT w tabeli, który sprawdza istnienie wiersza, a następnie aktualizuje/wstawia w zależności od tego, czy już istnieje. Jest to przykład, jak to zrobić dla SQL Server 2000+ na MSDN here:

CREATE TRIGGER IO_Trig_INS_Employee ON Employee 
INSTEAD OF INSERT 
AS 
BEGIN 
SET NOCOUNT ON 
-- Check for duplicate Person. If no duplicate, do an insert. 
IF (NOT EXISTS (SELECT P.SSN 
     FROM Person P, inserted I 
     WHERE P.SSN = I.SSN)) 
    INSERT INTO Person 
     SELECT SSN,Name,Address,Birthdate 
     FROM inserted 
ELSE 
-- Log attempt to insert duplicate Person row in PersonDuplicates table. 
    INSERT INTO PersonDuplicates 
     SELECT SSN,Name,Address,Birthdate,SUSER_SNAME(),GETDATE() 
     FROM inserted 
-- Check for duplicate Employee. If no duplicate, do an insert. 
IF (NOT EXISTS (SELECT E.SSN 
     FROM EmployeeTable E, inserted 
     WHERE E.SSN = inserted.SSN)) 
    INSERT INTO EmployeeTable 
     SELECT EmployeeID,SSN, Department, Salary 
     FROM inserted 
ELSE 
--If duplicate, change to UPDATE so that there will not 
--be a duplicate key violation error. 
    UPDATE EmployeeTable 
     SET EmployeeID = I.EmployeeID, 
      Department = I.Department, 
      Salary = I.Salary 
    FROM EmployeeTable E, inserted I 
    WHERE E.SSN = I.SSN 
END 
11

Można użyć @@ROWCOUNT aby sprawdzić, czy rząd powinien być włożony lub aktualizacja:

update table1 
set name = 'val2', itemname = 'val3', itemcatName = 'val4', itemQty = 'val5' 
where id = 'val1' 
if @@ROWCOUNT = 0 
insert into table1(id, name, itemname, itemcatName, itemQty) 
values('val1', 'val2', 'val3', 'val4', 'val5') 

w tym przypadku, jeżeli aktualizacja nie powiedzie się, nowy wiersz zostanie wstawiony

4

(moja odpowiedź jest poniżej, ale potem zdałem sobie sprawę, że jest to lepsze pytanie & odpowiedź na to co Insert into a MySQL table or update if exists)

Można sprawdzić, jeśli wiersz istnieje, a następnie INSERT lub UPDATE, ale gwarantuje to będzie wykonanie dwóch operacji SQL zamiast jednego:

  1. sprawdzić, czy rząd istnieje
  2. wkładka lub aktualizacji wiersza

lepszym rozwiązaniem jest zawsze aktualizować pierwszy, a jeśli nie wiersze zostały zaktualizowane, a następnie zrobić INSERT, tak:

update table1 
set name = 'val2', itemname = 'val3', itemcatName = 'val4', itemQty = 'val5' 
where id = 'val1' 

if @@ROWCOUNT = 0 
    insert into table1(id, name, itemname, itemcatName, itemQty) 
    values('val1', 'val2', 'val3', 'val4', 'val5') 

Spowoduje to wykonanie jednej operacji SQL lub dwóch operacji SQL, w zależności od tego, czy wiersz już istnieje.

Ale jeśli wydajność jest naprawdę problem, to musisz dowiedzieć się, czy operacje są bardziej prawdopodobne, INSERT lub UPDATE. Jeśli AKTUALIZACJE są bardziej powszechne, wykonaj powyższe czynności. Jeśli INSERT są bardziej powszechne, możesz to zrobić odwrotnie, ale musisz dodać obsługę błędów.

BEGIN TRY 
    insert into table1(id, name, itemname, itemcatName, itemQty) 
    values('val1', 'val2', 'val3', 'val4', 'val5') 
END TRY 
BEGIN CATCH 
    update table1 
    set name = 'val2', itemname = 'val3', itemcatName = 'val4', itemQty = 'val5' 
    where id = 'val1' 
END CATCH 

być naprawdę pewien, czy trzeba zrobić UPDATE lub INSERT, trzeba wykonać dwie operacje w ramach jednej transakcji. Teoretycznie, zaraz po pierwszej aktualizacji lub INSERT (lub nawet kontroli EXISTS), ale przed następną instrukcją INSERT/UPDATE, baza danych mogła ulec zmianie, powodując, że druga instrukcja i tak się nie powiedzie. Jest to niezwykle rzadkie, a koszty transakcji mogą nie być tego warte.

Alternatywnie można użyć pojedynczej operacji SQL o nazwie MERGE, aby wykonać INSERT lub UPDATE, ale to także prawdopodobnie przesada w przypadku tej operacji jednorzędowej.

Rozważ przeczytanie o SQL transaction statements, race conditions, SQL MERGE statement.

+0

Link do podanego pytania jest specyficzny dla MySql, gdzie ten wątek dotyczy serwera SQL, który nie ma opcji NA DUPLIKATU KLAWISZ AKTUALIZACJI. Czy mógłbyś wyjaśnić, którą odpowiedź masz na myśli, czy też jest to błąd z twojej strony? –

Powiązane problemy