2008-12-04 11 views
6

muszę zaktualizować rekord w bazie danych z następujących dziedzinWybór SQL: Aktualizuj, jeśli istnieje, Wstaw, jeśli nie - Porównywanie części daty?

[ID] int (AutoIncr. PK) 
[ScorerID] int 
[Score] int 
[DateCreated] smalldatetime 

Jeśli rekord istnieje tylko dniem dzisiejszym (powinna być sprawdzana część datę, a nie czas) i danego strzelca, ja lubię aktualizować wartość wyniku tego gościa i ten dzień. Jeśli zawodnik nie ma na dziś rekordu, chciałbym stworzyć nowy.

Dostaję siwych włosów próbujących dowiedzieć się, jak umieścić to w jednym (jest to możliwe?) SQL. Przy okazji używam bazy danych MSSQl i metody ExecuteNonQuery() do wydania zapytania.

+0

Którą wersję programu SQL Server używasz? – RobS

Odpowiedz

16
IF EXISTS (SELECT NULL FROM MyTable WHERE ScorerID = @Blah AND CONVERT(VARCHAR, DateCreated, 101) = CONVERT(VARCHAR, GETDATE(), 101)) 
    UPDATE MyTable SET blah blah blah 
ELSE 
    INSERT INTO MyTable blah blah blah 
1
CREATE PROCEDURE InsertOrUpdateScorer(@ScorerID INT, @Score INT) 
AS 
BEGIN 
    IF EXISTS (
    SELECT 1 
    FROM Scorer 
    WHERE ScorerID = @ScorerID AND DATEDIFF(dd, GETDATE(), DateCreated) = 0 
) 
    BEGIN 
    UPDATE 
     Scorer 
    SET 
     Score = @Score 
    WHERE 
     ScorerID = @ScorerID 

    RETURN @ScorerID 
    END 
    ELSE 
    BEGIN 
    INSERT 
     Scorer 
     (ScorerID, Score, DateCreated) 
    VALUES 
     (@ScorerID, @Score, GETDATE()) 

    RETURN SCOPE_IDENTITY() 
    END 
END 

Zastosowanie wartość zwracana procedurą, aby pobrać nową ScorerId.

SqlCommand UpdateScorer = New SqlCommand("InsertOrUpdateScorer", DbConn); 
UpdateScorer.CommandType = CommandType.StoredProcedure; 

SqlParameter RetValue = UpdateScorer.Parameters.Add("RetValue", SqlDbType.Int); 
RetValue.Direction = ParameterDirection.ReturnValue; 

SqlParameter Score = UpdateScorer.Parameters.Add("@Score", SqlDbType.Int); 
Score.Direction = ParameterDirection.Input; 

SqlParameter ScorerId = UpdateScorer.Parameters.Add("@ScorerID", SqlDbType.Int); 
ScorerId.Direction = ParameterDirection.Input; 

Score.Value = 15; // whatever 
ScorerId.Value = 15; // whatever 

UpdateScorer.ExecuteNonQuery(); 
Console.WriteLine(RetValue.Value); 
3

Inni użytkownicy uwzględnili T-SQL/apprroaches 2005 (i wcześniejsze). Chciałem tylko dodać, że jeśli masz szczęście pracować z SQL Server 2008, możesz skorzystać z nowej instrukcji Merge (czasem nazywanej Upsert).

Mam problem ze znalezieniem wpisu w blogu lub artykułu, który wyjaśnia to dalej, ale znalazłem to raczej (1) helpful entry. Oficjalna wejście MSDN jest (2) here.

(1) [http://www.sqlservercurry.com/2008/05/sql-server-2008-merge-statement.html]
(2) [http://msdn.microsoft.com/en-us/library/bb510625.aspx]

1

Dla przypadku, gdy pożądane jest, aby zaktualizować lub wprowadzeniu wszystkich wartości na raz, a nie tylko na jednej płycie, że stosuje się ten fragment

1-ty Uruchom skrypt aktualizacji

UPDATE Table1 
SET OPIS = T1.OPIS 
FROM 
    Table1 AS T 
INNER JOIN 
    Table2 AS T1 
    ON 
     T.col = T1.col; 

Następnie wykonaj skrypt insert

INSERT INTO Table1 
SELECT * FROM 
    (
     SELECT T1.* Table2 AS T1 
     LEFT JOIN Table1 AS T2 ON (T2.col = T1.col) 
     WHERE T2.col IS NULL 
    ) AS T; 

Mam nadzieję, że ktoś uznał to za przydatne.

Odpowiednikiem tego w MySQL (w niektórych przypadkach) jest mniej więcej tak:

 
INSERT INTO table (a,b,c) VALUES (1,2,3) 
    ON DUPLICATE KEY UPDATE c=c+1; 

Ktoś może okazało się, że jest to związane z artykułem w Solutions for INSERT OR UPDATE on SQL Server

Zaktualizowana wersja użyciu MERGE (Transact-SQL):

DECLARE @USER_ID AS INT=76; 
DECLARE @TYPE AS NVARCHAR(MAX)='set.global'; 
DECLARE @FKEY AS NVARCHAR(MAX)='21'; 
DECLARE @DATA AS NVARCHAR(MAX)='test'; 

     begin tran 
      MERGE UserData 
      USING (SELECT @USER_ID, @TYPE, @FKEY, @DATA) AS Source([UserId], [Type], [FKey], [Data]) 
      ON (UserData.[UserId] = Source.[UserId] AND UserData.[Type] = Source.[Type] AND (UserData.[FKey] = Source.[FKey] OR (Source.[FKey] IS NULL AND UserData.[FKey] IS NULL))) 
      WHEN MATCHED 
      THEN 
       UPDATE SET [Data] = Source.[Data] 
      WHEN NOT MATCHED BY TARGET THEN 
       INSERT 
          ([UserId] 
          ,[Type] 
          ,[FKey] 
          ,[Data]) 
        VALUES 
          (Source.[UserId] 
          ,Source.[Type] 
          ,Source.[FKey] 
          ,Source.[Data]); 

     commit tran