2008-12-04 37 views
6

Tôi cần cập nhật một bản ghi trong cơ sở dữ liệu với các lĩnh vực sauChọn SQL: Cập nhật nếu có, Chèn nếu không - Với so sánh một phần ngày?

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

Nếu một kỷ lục tồn tại cho ngày todays (chỉ có phần ngày nên được kiểm tra, không phải là thời gian) và một cầu thủ ghi bàn nhất định, tôi muốn muốn cập nhật giá trị điểm số cho anh chàng này và ngày này. Nếu người ghi bàn không có hồ sơ cho ngày hôm nay, tôi muốn tạo một bản ghi mới.

Tôi nhận được mái tóc màu xám cố gắng tìm cách để đưa điều này vào một câu lệnh sql đơn lẻ (có thể là điều này có thể không?). Bằng cách tôi đang sử dụng một cơ sở dữ liệu MSSQl và phương pháp ExecuteNonQuery() để phát hành truy vấn.

+0

Bạn đang sử dụng phiên bản SQL Server nào? – RobS

Trả lời

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 

Sử dụng giá trị trả về của thủ tục để lấy ScorerId mới.

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

Những người khác đã đề cập đến T-SQL/apprroaches tương thích 2005 (và trước). Tôi chỉ muốn thêm rằng nếu bạn đủ may mắn để làm việc với SQL Server 2008, bạn có thể tận dụng lợi thế của câu lệnh Merge mới (đôi khi được gọi là Upsert).

Tôi gặp khó khăn trong việc tìm kiếm bài viết hoặc bài viết blog giải thích thêm về nó, nhưng tôi đã tìm thấy điều này thay vì (1) helpful entry. Mục chính thức MSDN là (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

Đối với trường hợp khi là mong muốn để cập nhật hoặc chèn tất cả các giá trị cùng một lúc, không chỉ đối với một hồ sơ tôi đã sử dụng đoạn mã này

1st chạy kịch bản cập nhật

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

Sau đó làm kịch bản chèn

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; 

Hy vọng rằng ai đó thấy điều này hữu ích.

Tương đương này trong MySql (trong một số trường hợp) là một cái gì đó như thế này:

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

Ai đó có thể thấy rằng điều này có liên quan đến bài viết ở Solutions for INSERT OR UPDATE on SQL Server

Cập nhật phiên bản sử dụng 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 
Các vấn đề liên quan