[SQL] 이를 이미 없으면 만 행을 삽입
SQL이를 이미 없으면 만 행을 삽입
난 항상 그것을 달성하기 위해 다음과 같은 것을 사용했다 :
INSERT INTO TheTable
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WHERE
PrimaryKey = @primaryKey)
부하 일단 ...하지만, 기본 키 위반이 발생했습니다. 이것은 전혀이 테이블에 삽입하는 유일한 문입니다. 그래서 위의 문이 원자 아님을 의미합니까?
문제는이 마음대로 다시 거의 불가능하다는 것이다.
아마도 내가 다음과 같은 뭔가를 변경할 수 있습니다 :
INSERT INTO TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
WHERE
PrimaryKey = @primaryKey)
어쩌면 내가 잘못 잠금을 사용하거나 너무 많은 잠금 또는 무언가를 사용하고, 비록.
대답은 "IF (SELECT COUNT (*) ... INSERT"등을 제안하는 어디 stackoverflow.com에 다른 질문을 봐 왔지만, 나는 하나의 SQL 문은 원자 될 것이라고 (아마도 잘못된) 가정에서 항상이었다.
사람이 어떤 아이디어가 있습니까?
해결법
-
==============================
1.무엇 "JFDI"패턴은 어떻습니까?
무엇 "JFDI"패턴은 어떻습니까?
BEGIN TRY INSERT etc END TRY BEGIN CATCH IF ERROR_NUMBER() <> 2627 RAISERROR etc END CATCH
진심으로,이 특히 높은 볼륨으로, 빠르고 잠금없이 대부분의 동시입니다. 무엇 UPDLOCK이 에스컬레이트 전체 테이블이 잠겨 있다면?
읽기 수업 4 :
-
==============================
2.원래는 제시되지 않은 HOLDLOCK을 추가했다. 이 힌트없이 버전을 무시하십시오.
원래는 제시되지 않은 HOLDLOCK을 추가했다. 이 힌트없이 버전을 무시하십시오.
마찬가지로 지금까지 내가 걱정으로,이 충분해야한다 :
INSERT INTO TheTable SELECT @primaryKey, @value1, @value2 WHERE NOT EXISTS (SELECT 0 FROM TheTable WITH (UPDLOCK, HOLDLOCK) WHERE PrimaryKey = @primaryKey)
당신이 실제로 존재하는 경우 행을 업데이트하고 그렇지 않은 경우 삽입 할 경우에도, 당신은이 질문에 유용 할 수 있습니다.
-
==============================
3.당신은 MERGE를 사용할 수 있습니다 :
당신은 MERGE를 사용할 수 있습니다 :
MERGE INTO Target USING (VALUES (@primaryKey, @value1, @value2)) Source (key, value1, value2) ON Target.key = Source.key WHEN MATCHED THEN UPDATE SET value1 = Source.value1, value2 = Source.value2 WHEN NOT MATCHED BY TARGET THEN INSERT (Name, ReasonType) VALUES (@primaryKey, @value1, @value2)
-
==============================
4.이 "공식적인"방법인지는 모르겠지만, 당신은 INSERT를 시도하고 실패하면 UPDATE로 다시 떨어질 수있다.
이 "공식적인"방법인지는 모르겠지만, 당신은 INSERT를 시도하고 실패하면 UPDATE로 다시 떨어질 수있다.
-
==============================
5.첫째, 지역 사회에 대한 공헌 우리의 남자 @gbn 밖으로 큰 소리. 심지어 나는 그의 조언을 다음과 같은 자신을 발견하는 빈도를 설명하기 시작 할 수 없습니다.
첫째, 지역 사회에 대한 공헌 우리의 남자 @gbn 밖으로 큰 소리. 심지어 나는 그의 조언을 다음과 같은 자신을 발견하는 빈도를 설명하기 시작 할 수 없습니다.
어쨌든, 충분히 팬보이 - 보내고.
아마도 그의 대답에 약간 추가하려면는 "강화". 사람들을 위해, 나처럼 <> 2627 시나리오에서 수행하는 것과 불안 느낌 왼쪽 (더 빈 CATCH이 옵션을 선택하지 않습니다). 나는 TechNet의에서이 작은 덩어리를 발견했다.
BEGIN TRY INSERT etc END TRY BEGIN CATCH IF ERROR_NUMBER() <> 2627 BEGIN DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity INT; DECLARE @ErrorState INT; SELECT @ErrorMessage = ERROR_MESSAGE(), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); RAISERROR ( @ErrorMessage, @ErrorSeverity, @ErrorState ); END END CATCH
-
==============================
6.나는 다른 방법을 사용하여 과거에 비슷한 작업을 완료했습니다. 첫째, 나는 차 키를 보유하는 변수를 선언합니다. 그리고 나는 그 값을 기록 찾습니다 SELECT 문의 출력하여 해당 변수를 채 웁니다. 그럼 내가 할 수 및 IF 문. 기본 키가 null 인 경우, 다음, 다른, 삽입 할 몇 가지 오류 코드를 반환합니다.
나는 다른 방법을 사용하여 과거에 비슷한 작업을 완료했습니다. 첫째, 나는 차 키를 보유하는 변수를 선언합니다. 그리고 나는 그 값을 기록 찾습니다 SELECT 문의 출력하여 해당 변수를 채 웁니다. 그럼 내가 할 수 및 IF 문. 기본 키가 null 인 경우, 다음, 다른, 삽입 할 몇 가지 오류 코드를 반환합니다.
DECLARE @existing varchar(10) SET @existing = (SELECT primaryKey FROM TABLE WHERE param1field = @param1 AND param2field = @param2) IF @existing is not null BEGIN INSERT INTO Table(param1Field, param2Field) VALUES(param1, param2) END ELSE Return 0 END
from https://stackoverflow.com/questions/3407857/only-inserting-a-row-if-its-not-already-there by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떻게 MySQL을 사용 두 날짜 사이 쿼리합니까? (0) | 2020.03.09 |
---|---|
[SQL] 어떻게 (또는 내가 수 있습니다) 여러 열에서 DISTINCT 선택합니까? (0) | 2020.03.09 |
[SQL] 두 날짜 사이에 작업 일 카운트 (0) | 2020.03.09 |
[SQL] 어떻게 PostgreSQL의에서 many-to-many 관계를 구현하는 방법? (0) | 2020.03.09 |
[SQL] 여러 열의 SQL MAX? (0) | 2020.03.09 |