[sql] 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 위기


답변

문제를 명확히하기 위해 @@Identity:

예를 들어, 테이블을 삽입하고 해당 테이블 @@Identity에 삽입을 수행하는 트리거가있는 경우 트리거의 삽입 ( log_id또는 다른 것) scope_identity()에서 ID를 반환하는 반면 원래 테이블의 삽입에서 ID를 반환합니다.

당신은 어떤 트리거가없는, 그래서 만약 scope_identity()@@identity같은 값을 반환합니다. 트리거가있는 경우 원하는 값에 대해 생각해야합니다.


답변

Scope Identity: 실행중인 저장 프로 시저 내에 추가 된 마지막 레코드의 ID.

@@Identity: 쿼리 일괄 처리 내에 추가 된 마지막 레코드의 ID 또는 쿼리의 결과 (예 : 삽입을 수행하는 프로 시저)는 트리거를 시작한 다음 레코드를 삽입하면 트리거에서 삽입 된 레코드의 ID를 반환합니다.

IdentCurrent: 테이블에 할당 된 마지막 ID입니다.