2008-12-04 68 views
6

我需要以下字段SQL選擇:如果存在則更新,如果不存在則插入 - 是否包含日期部件比較?

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

如果記錄存在今天的日期(只有日期部分應檢查,而不是時間)和給定的得分手來更新數據庫中的記錄,我會喜歡更新這個人和這一天的分數值。如果記分員今天沒有記錄,我想創建一個新記錄。

我越來越灰白的頭髮想要怎麼把這個變成單​​一的(這是可能的嗎?)sql語句。順便說一句,我使用MSSQl數據庫和ExecuteNonQuery()方法來發出查詢。

+0

您正在使用哪個版本的SQL Server? – RobS 2008-12-04 14:06:40

回答

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 

使用方法的返回值來獲取新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

其他人已經涵蓋了2005年(和之前)兼容的T-SQL/apprroaches。我只想補充一點,如果您足夠幸運能夠使用SQL Server 2008,則可以利用新的Merge(有時稱爲Upsert)語句。

我很難找到一個博客條目或文章,進一步解釋它,但我確實發現這個,而不是(1) helpful entry。官方MSDN條目是(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

對於當需要更新或一次插入所有的值的情況下,不僅對一個記錄我用這個片段

第一次運行更新腳本

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

然後執行插入腳本

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; 

希望有人認爲這有用。

這在MySQL中相當於(在某些情況下)是這樣的:

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

有人可以發現,這是在Solutions for INSERT OR UPDATE on SQL Server

相關的文章更新的版本使用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