SQL Select: Atualização se existir, Inserir se não - Com comparação data parte?
-
19-08-2019 - |
Pergunta
Eu preciso atualizar um registro em um banco de dados com os seguintes campos
[ID] int (AutoIncr. PK)
[ScorerID] int
[Score] int
[DateCreated] smalldatetime
Se existe um registro data de hoje para (apenas a parte de data deve ser verificada, e não o tempo) e um determinado marcador, eu gostaria de atualizar o valor de pontuação para esse cara e esse dia. Se o marcador não tem um registro para hoje, eu gostaria de criar um novo.
Eu estou começando cabelo grisalho tentando descobrir como colocar isso em um único (isto é possível?) Instrução SQL. Pelo jeito que eu estou usando um banco de dados MSSQL e o método ExecuteNonQuery()
para emitir a consulta.
Solução
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
Outras dicas
Os outros caras têm coberto de 2005 (e anteriores) compatíveis T-SQL / apprroaches. Eu só queria acrescentar que, se você é o suficiente sorte de estar trabalhando com o SQL Server 2008, você poderia tirar proveito da nova mala direta (por vezes referido como Upsert) comunicado.
I teve problemas para encontrar uma entrada de blog ou artigo que explica-lo ainda mais, mas eu encontrei este em vez (1) útil entrada . A entrada oficial MSDN é (2) aqui.
(1) [ http: // www.sqlservercurry.com/2008/05/sql-server-2008-merge-statement.html]
(2) [ http://msdn.microsoft.com/ en-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
Use o valor de retorno do procedimento para agarrar a nova 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);
Para o caso quando se deseja atualizar ou inserir todos os valores de uma só vez, não só para um registro que eu usei esse trecho
1 Execute o script de atualização
UPDATE Table1 SET OPIS = T1.OPIS FROM Table1 AS T INNER JOIN Table2 AS T1 ON T.col = T1.col;
Em seguida, fazer o script de inserção
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;
A esperança que alguém encontrou este útil.
O equivalente a isso no MySql (em alguns casos) é algo como isto:
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
Alguém pode descobriram que isto está relacionado com o artigo em para INSERT ou UPDATE no SQL Server
Versão atualizada usando 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