나는 알고있다 Scope_Identity()
, Identity()
, @@Identity
, 및 Ident_Current()
모든 식별 컬럼의 값을 얻을 수 있지만 그 차이를 알고 싶어요.
내가 겪고있는 논쟁의 일부는 위의 기능에 적용되는 범위에 따라 무엇을 의미합니까?
나는 또한 그것들을 사용하는 다른 시나리오의 간단한 예를 좋아할 것입니까?
나는 알고있다 Scope_Identity()
, Identity()
, @@Identity
, 및 Ident_Current()
모든 식별 컬럼의 값을 얻을 수 있지만 그 차이를 알고 싶어요.
내가 겪고있는 논쟁의 일부는 위의 기능에 적용되는 범위에 따라 무엇을 의미합니까?
나는 또한 그것들을 사용하는 다른 시나리오의 간단한 예를 좋아할 것입니까?
답변:
@@identity
함수는 같은 세션에서 생성 된 마지막 아이디를 반환합니다.scope_identity()
함수는 동일한 세션과 동일한 범위에서 만들어진 마지막 아이디를 반환합니다.ident_current(name)
어떤 세션에서 특정 테이블이나 뷰에 대해 생성 된 마지막 ID를 반환합니다.identity()
함수는 아이디를 얻는 데 사용되지 않으며 select...into
쿼리 에서 아이디를 만드는 데 사용됩니다 .세션은 데이터베이스 연결입니다. 범위는 현재 쿼리 또는 현재 저장 프로 시저입니다.
scope_identity()
와 @@identity
기능이 다른 상황 은 테이블에 트리거가있는 경우입니다. 레코드를 삽입하는 쿼리가있는 경우 트리거가 다른 레코드를 어딘가에 삽입하면 scope_identity()
함수는 쿼리에 @@identity
의해 생성 된 ID를 반환하고 함수는 트리거에 의해 생성 된 ID를 반환합니다.
따라서 일반적으로 scope_identity()
함수를 사용합니다 .
좋은 질문.
@@IDENTITY
: SQL 연결 (SPID)에서 생성 된 마지막 ID 값을 반환합니다. 대부분의 경우 원하는대로되지만 때로는 그렇지 않습니다 (트리거에 대한 응답으로 트리거가 시작되고 트리거가 INSERT
다른 INSERT
명령문을 실행하는 경우).
SCOPE_IDENTITY()
: 현재 범위에서 생성 된 마지막 ID 값 (즉, 저장 프로 시저, 트리거, 함수 등)을 반환합니다.
IDENT_CURRENT()
: 특정 테이블의 마지막 ID 값을 반환합니다. 를 사용하여 ID 값을 가져 오지 마십시오. INSERT
경쟁 조건이 적용됩니다 (예 : 동일한 테이블에 행을 삽입하는 여러 연결).
IDENTITY()
: 테이블의 열을 ID 열로 선언 할 때 사용됩니다.
자세한 내용은 http://msdn.microsoft.com/en-us/library/ms187342.aspx를 참조 하십시오 .
요약 : 행 을 삽입 할 때 방금 삽입 한 행의 ID 열 값을 알고 싶다면 항상을 사용하십시오 SCOPE_IDENTITY()
.
범위와 세션의 차이점을 이해하면 이러한 방법을 이해하는 것이 매우 쉽습니다.
Adam Anderson 의 매우 멋진 블로그 게시물 은 이러한 차이점을 설명합니다.
세션 은 명령을 실행하는 현재 연결을 의미합니다.
범위 는 명령의 즉각적인 컨텍스트를 의미합니다. 모든 저장 프로 시저 호출은 자체 범위에서 실행되고 중첩 된 호출은 호출 프로 시저 범위 내에서 중첩 된 범위에서 실행됩니다. 마찬가지로 응용 프로그램 또는 SSMS에서 실행 된 SQL 명령은 자체 범위에서 실행되며 해당 명령이 트리거를 발생하면 각 트리거는 자체 중첩 범위 내에서 실행됩니다.
따라서 세 가지 신원 검색 방법의 차이점은 다음과 같습니다.
@@identity
이 세션 에서 생성 된 마지막 아이디 값을 제외한 모든 범위를 반환합니다 .
scope_identity()
이 세션 과이 범위 에서 생성 된 마지막 ID 값을 반환합니다 .
ident_current()
에서 특정 테이블에 대해 생성 된 마지막 ID 값을 반환하는 모든 세션 및 모든 범위를.
범위 는 전역 범위와 달리 INSERT
명령문 을 수행하는 코드 컨텍스트를 의미합니다 .SCOPE_IDENTITY()
@@IDENTITY
CREATE TABLE Foo(
ID INT IDENTITY(1,1),
Dummy VARCHAR(100)
)
CREATE TABLE FooLog(
ID INT IDENTITY(2,2),
LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END
INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY
다른 결과를 제공합니다.
@David Freitas가 언급 한 버그와 2012 년에 도입 된 새로운 시퀀스 기능과의 비 호환성 때문에이 세 가지를 멀리하는 것이 좋습니다. 대신 OUTPUT 절을 사용하여 삽입 된 ID 값을 얻을 수 있습니다. 다른 장점은 OUTPUT이 둘 이상의 행을 삽입 한 경우에도 작동한다는 것입니다.
자세한 내용과 예는 여기를 참조하십시오. ID 위기
이 책 에서 또 다른 좋은 설명이 있습니다 .
SCOPE_IDENTITY와 @@ IDENTITY의 차이점에 대해 다음 세 개의 명령문으로 스토어드 프로 시저 P1이 있다고 가정하십시오
.-새 ID 값을 생성하는 INSERT-새
프로 시저를 생성하는 INSERT 문이있는 스토어드 프로 시저 P2에 대한 호출 identity
value-함수 SCOPE_IDENTITY 및 @@ IDENTITY를 쿼리하는 문 SCOPE_IDENTITY 함수는 P1 (동일한 세션 및 범위)에서 생성 된 값을 반환합니다. @@ IDENTITY 함수는 P2에 의해 생성 된 값을 반환합니다 (범위에 관계없이 동일한 세션).