【问题标题】:SQL Select: Update if exists, Insert if not - With date part comparison?SQL Select:如果存在则更新,如果不存在则插入 - 使用日期部分比较?
【发布时间】:2008-12-04 12:06:06
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您使用的是哪个版本的 SQL Server?

标签: sql sql-server sql-update


【解决方案1】:
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

【讨论】:

    【解决方案2】:

    其他人已经介绍了 2005(和之前)兼容的 T-SQL/方法。我只想补充一点,如果您有幸使用 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]

    【讨论】:

      【解决方案3】:
      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);
      

      【讨论】:

        【解决方案4】:

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

        第一次运行更新脚本

        更新表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;

        有人可以发现这与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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-05
          • 2018-09-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-31
          • 1970-01-01
          • 2016-05-15
          相关资源
          最近更新 更多