6

我需要使用以下字段更新数据库中的记录

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

如果存在今天日期的记录(只应检查日期部分,而不是时间)和给定的得分手,我想更新这个人和这一天的得分值。如果得分手没有今天的记录,我想创造一个新的记录。

我正试图弄清楚如何将其放入单个(这可能吗?)sql语句中。顺便说一句,我使用的是 MSSQl 数据库和ExecuteNonQuery()发出查询的方法。

4

4 回答 4

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
于 2008-12-04T12:12:45.283 回答
3

其他人已经介绍了 2005(和之前)兼容的 T-SQL/方法。我只想补充一点,如果您有幸使用 SQL Server 2008,您可以利用新的 Merge(有时称为 Upsert)语句。

我很难找到进一步解释它的博客条目或文章,但我确实发现这个(1) 很有帮助的条目。官方 MSDN 条目是(2) 这里。

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

于 2008-12-04T14:11:01.223 回答
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);
于 2008-12-04T12:17:38.720 回答
1

对于需要一次更新或插入所有值的情况,不仅仅是一条记录,我使用了这个片段

第一次运行更新脚本

更新表1
设置 OPIS = T1.OPIS
从
    表 1 AS T
内部联接
    表2 AS T1
    在
        T.col = T1.col;

然后执行插入脚本

插入表 1
选择 * 从
    (
        选择 T1.* 表 2 作为 T1
        LEFT JOIN Table1 AS T2 ON (T2.col = T1.col)
        T2.col 为空
    ) 作为 T;

希望有人发现这很有用。

MySql 中的 this 等价物(在某些情况下)是这样的:

插入表 (a,b,c) 值 (1,2,3)
  重复密钥更新 c=c+1;

有人可以发现这与SQL Server 上的 INSERT OR UPDATE 解决方案中的文章有关

使用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
于 2013-09-20T09:52:55.300 回答