SQL Select : 업데이트가 존재하는 경우 업데이트, 그렇지 않은 경우 삽입 - 날짜 부품 비교?
-
19-08-2019 - |
문제
다음 필드로 데이터베이스에서 레코드를 업데이트해야합니다.
[ID] int (AutoIncr. PK)
[ScorerID] int
[Score] int
[DateCreated] smalldatetime
오늘 날짜에 대한 기록이 존재하는 경우 (시간이 아닌 날짜 부분 만 확인해야 함) 주어진 득점자 인 경우이 사람과 오늘의 점수 값을 업데이트하고 싶습니다. 득점자에게 오늘 기록이 없다면 새로운 기록을 만들고 싶습니다.
나는 이것을 단일 (이것이 가능합니까?) SQL 문에 이것을 넣는 방법을 알아 내려고 회색 머리카락을 얻고 있습니다. 그건 그렇고 나는 MSSQL 데이터베이스를 사용하고 있습니다. ExecuteNonQuery()
쿼리를 발행하는 방법.
해결책
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
다른 팁
다른 사람들은 2005 년 (및 이전) 호환 T-SQL/orproaches를 다루었습니다. SQL Server 2008과 함께 일할만큼 운이 좋으면 새로운 병합 (때로는 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
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
절차의 반환 값을 사용하여 새로운 스코어리드를 잡으십시오.
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);
한 번에 모든 값을 업데이트하거나 삽입하려는 경우, 한 레코드뿐만 아니라이 스 니펫을 사용했습니다.
첫 번째 업데이트 스크립트를 실행하십시오
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;
누군가는 이것이 기사와 관련이 있음을 발견 할 수 있습니다. SQL Server의 삽입 또는 업데이트 솔루션
업데이트 된 버전 사용 병합 (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