삽입을 통해 생성 한 ID 값을 얻는 가장 좋은 방법은 무엇입니까? 이 진술이 성능 측면에서 어떤 영향을 미칩니 까?
SCOPE_IDENTITY()
- 집계 함수
MAX()
TOP 1
TableName에서 IdentityColumn 선택ORDER BY IdentityColumn DESC
삽입을 통해 생성 한 ID 값을 얻는 가장 좋은 방법은 무엇입니까? 이 진술이 성능 측면에서 어떤 영향을 미칩니 까?
SCOPE_IDENTITY()
MAX()
TOP 1
TableName에서 IdentityColumn 선택ORDER BY IdentityColumn DESC
답변:
SCOPE_IDENTITY()
단일 행을 삽입하고 생성 된 ID를 검색하려는 경우 사용하십시오 .
CREATE TABLE #a(identity_column INT IDENTITY(1,1), x CHAR(1));
INSERT #a(x) VALUES('a');
SELECT SCOPE_IDENTITY();
결과:
----
1
OUTPUT
여러 행을 삽입하고 생성 된 ID 세트 를 검색해야하는 경우이 절을 사용하십시오 .
INSERT #a(x)
OUTPUT inserted.identity_column
VALUES('b'),('c');
결과:
----
2
3
왜 이것이 가장 빠른 옵션입니까?
기본적으로, 격리 수준 및 / 또는 여러 사용자가 올바른 것으로 보장되는 것은 성능뿐입니다. 정확성 측면을 무시하더라도 SQL Server는 삽입 된 값을 SCOPE_IDENTITY()
메모리 에 보유 하므로 당연히 테이블이나 시스템 테이블에 대해 자체 격리 쿼리를 실행하는 것보다 빠릅니다.
정확성 측면을 무시하는 것은 우체부에게 오늘의 우편물을 잘 전달했다고 말하는 것과 같습니다. 그는 자신의 평균 시간보다 10 분 더 빨리 경로를 완료했습니다.
다음을 사용 하지 마십시오 :
@@IDENTITY
-예를 들어 ID 열이있는 테이블에 자체 ID 열이있는 다른 테이블에 삽입하는 트리거가있는 경우와 같이 모든 시나리오에서 사용할 수 없으므로 잘못된 값을 다시 얻게됩니다.IDENT_CURRENT()
- 나는 이것에 대해 자세히 다루지 여기 및 코멘트뿐만 아니라 유용한 독서를하지만, 본질적으로, 동시성에 따라, 당신은 종종 잘못된 답변을 얻을 것입니다.MAX()
또는 TOP 1
- MAX()
다른 사람이 아닌 사람이 되도록하기 위해 직렬화 가능한 격리로 두 명령문을 보호해야합니다 . 이것은을 사용하는 것보다 훨씬 비쌉니다 SCOPE_IDENTITY()
.이 함수는 또한 두 개 이상의 행을 삽입 할 때마다 실패하며 생성 된 모든 ID 값이 필요합니다 OUTPUT
. 절의 유일한 옵션 입니다.
성능과는 별도로, 그들은 모두 다른 의미를 가지고 있습니다.
SCOPE_IDENTITY()
현재 범위 내에서 직접 모든 테이블에 삽입 된 마지막 ID 값을 제공합니다 (범위 = 배치, 저장 프로 시저 등. 그러나 현재 범위에서 시작된 트리거 내에는 포함되지 않음).
IDENT_CURRENT()
당신에서 특정 테이블에 삽입 된 마지막 ID 값을 줄 것이다 어떤 에 의해 범위, 어떤 사용자.
@@IDENTITY
테이블이나 범위에 관계없이 현재 연결에 대한 가장 최근의 INSERT 문에 의해 생성 된 마지막 ID 값을 제공합니다. (참고 : Access는이 기능을 사용하므로 ID 열이있는 테이블에 값을 삽입하는 트리거에 문제가 있습니다.)
사용 MAX()
하거나하는 것은 TOP 1
테이블이 음의 신원 단계를 가지고, 또는 삽입 행했다 경우 당신에게 완전히 잘못된 결과를 줄 수있는 SET IDENTITY_INSERT
플레이를. 다음은이 모든 것을 보여주는 스크립트입니다.
CREATE TABLE ReverseIdent (
id int IDENTITY(9000,-1) NOT NULL PRIMARY KEY CLUSTERED,
data char(4)
)
INSERT INTO ReverseIdent (data)
VALUES ('a'), ('b'), ('c')
SELECT * FROM ReverseIdent
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9000
SET IDENTITY_INSERT ReverseIdent ON
INSERT INTO ReverseIdent (id, data)
VALUES (9005, 'd')
SET IDENTITY_INSERT ReverseIdent OFF
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9005
요약 :와 스틱 SCOPE_IDENTITY()
, IDENT_CURRENT()
또는 @@IDENTITY
하고 있는지 확인 당신이 하나의 반환 당신이 실제로 필요로하는을 사용하고 있습니다.
IDENT_CURRENT()
하고 @@IDENTITY
때 자신의 스크립트는 출력 잘못된 결과가 있음을 보여줍니다?
IDENT_CURRENT()
반환되는 것입니다. MAX ()는 id가 뒤로 계산되므로 IDENTITY_INSERT
9005는 생성 된 ID 값이 아니므로에 반영되지 않으므로 첫 번째 행 이후의 올바른 값을 반환 하지 않습니다 IDENT_CURRENT()
. 그러나 당신이 실제로 무엇을 반환 하는 경우에 "잘못된"결과를 반환 할 수 있습니다SCOPE_IDENTITY()
. 작업에 적합한 도구를 선택하십시오.
@@IDENTITY
결코 신원 가치를 창출하는 이상적인 방법이 아니라는 데 동의 합니다. 요점은 MAX()
또는의 TOP 1
신뢰성이 떨어지는 버전과 같다는 IDENT_CURRENT()
것입니다. 유지 보수 작업이나 무언가에 유용 할 수 있습니다.