2008-12-04 69 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