Sélection SQL: Mettre à jour si existant, insérer si non - avec comparaison des parties de date?

StackOverflow https://stackoverflow.com/questions/340366

  •  19-08-2019
  •  | 
  •  

Question

Je dois mettre à jour un enregistrement dans une base de données avec les champs suivants

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

Si un enregistrement existe pour la date du jour (seule la partie de la date doit être vérifiée, pas l'heure) et un marqueur donné, j'aimerais mettre à jour la valeur du score pour ce gars et cette journée. Si le marqueur n'a pas de record pour aujourd'hui, j'aimerais en créer un nouveau.

Je commence à avoir des cheveux gris en essayant de comprendre comment mettre cela dans une seule déclaration (est-ce possible?) sql. En passant, j'utilise une base de données MSSQl et la méthode ExecuteNonQuery () pour émettre la requête.

Était-ce utile?

La solution

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

Autres conseils

Les autres personnes ont couvert les approchages / T-SQL compatibles de 2005 (et les précédents). Je voulais simplement ajouter que si vous avez la chance de travailler avec SQL Server 2008, vous pouvez tirer parti de la nouvelle instruction Merge (parfois appelée Upsert).

J'ai eu du mal à trouver une entrée de blog ou un article qui l'explique davantage, mais je l'ai trouvé plutôt (1) entrée utile . L’entrée MSDN officielle est (2) ici.

.

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

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

Utilisez la valeur de retour de la procédure pour récupérer le nouveau 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);

Pour le cas où l'on souhaite mettre à jour ou insérer toutes les valeurs à la fois, pas seulement pour un enregistrement, j'ai utilisé cet extrait

1ère exécution du script de mise à jour

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

Ensuite, insérez le script

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;

J'espère que quelqu'un a trouvé cela utile.

L'équivalent de ceci dans MySql (dans certains cas) ressemble à ceci:

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

Quelqu'un peut dire que cela est lié à l'article sur Solutions pour INSÉRER OU MISE À JOUR sur SQL Server

Version mise à jour à l'aide de FUSION (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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top