Scope_Identity (), Identity (), @@ Identity 및 Ident_Current ()의 차이점은 무엇입니까?


192

나는 알고있다 Scope_Identity(), Identity(), @@Identity, 및 Ident_Current()모든 식별 컬럼의 값을 얻을 수 있지만 그 차이를 알고 싶어요.

내가 겪고있는 논쟁의 일부는 위의 기능에 적용되는 범위에 따라 무엇을 의미합니까?

나는 또한 그것들을 사용하는 다른 시나리오의 간단한 예를 좋아할 것입니까?


2
SCOPE_IDENTITY 및 @@ IDENTITY에 대해 SQL Server에 존재하는 병렬 실행 버그를 잊지 마십시오. support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David d C e Freitas

@DaviddCeFreitas-버그에 대해 궁금하지만 링크가 끊어진 것으로 보입니다 (적어도 ASP 오류가 발생 함).
rory.ap

2
실제로, 나는 그것을 발견했다 : support.microsoft.com/en-us/kb/2019779
rory.ap

이전 KB 기사
George Birbilis

답변:


396
  • @@identity함수는 같은 세션에서 생성 된 마지막 아이디를 반환합니다.
  • scope_identity()함수는 동일한 세션과 동일한 범위에서 만들어진 마지막 아이디를 반환합니다.
  • ident_current(name)어떤 세션에서 특정 테이블이나 뷰에 대해 생성 된 마지막 ID를 반환합니다.
  • identity()함수는 아이디를 얻는 데 사용되지 않으며 select...into쿼리 에서 아이디를 만드는 데 사용됩니다 .

세션은 데이터베이스 연결입니다. 범위는 현재 쿼리 또는 현재 저장 프로 시저입니다.

scope_identity()@@identity기능이 다른 상황 은 테이블에 트리거가있는 경우입니다. 레코드를 삽입하는 쿼리가있는 경우 트리거가 다른 레코드를 어딘가에 삽입하면 scope_identity()함수는 쿼리에 @@identity의해 생성 된 ID를 반환하고 함수는 트리거에 의해 생성 된 ID를 반환합니다.

따라서 일반적으로 scope_identity()함수를 사용합니다 .


14
"scope_identity () 및 @@ identity ..."문단 때문에 이것을 답으로 선택했습니다. 더 명확하게 설명했습니다.
Tebo

1
David Freitas가 위에서 언급했듯이 scope_identity 구현에 버그가 있으므로 다른 방법 인 OUTPUT 절을 사용하는 것이 좋습니다. 아래 답변을 참조하십시오.
Sebastian Meine

@Guffa- "세션은 데이터베이스 연결입니다." 연결 풀링을 사용하는 경우 연결에서 세션이 유지됩니까?
Dave Black

1
이것은 역할 모델 답변입니다. 특히, SQL 및 SQL Server 작업은 이상 할 수 있으며, 이는 여전히 정보를 제공하면서도 매우 명확하고 평신도의 방식으로 설명합니다. 다른 SE 답변이 많이하는 두 데이터베이스 전문가간에 의사 소통되는 것처럼 들리지 않습니다.
Panzercrisis

내가 읽은 것에서 @DaveBlack : 아니오, 세션은 풀에서 유지되지 않으며 세션은 connect () 후 스크립트 실행에 고유합니다. 풀링시 ... SQL Server 용 PHP는 ODBC 연결 풀링을 사용합니다. 풀에서 연결을 사용하면 연결 상태가 재설정됩니다. 연결을 닫으면 연결이 풀로 돌아갑니다. (참고 : linux / mac에 대한 설명 참조) docs.microsoft.com/en-us/sql/connect/php/…
GDmac

42

좋은 질문.

  • @@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().


16

범위와 세션의 차이점을 이해하면 이러한 방법을 이해하는 것이 매우 쉽습니다.

Adam Anderson 의 매우 멋진 블로그 게시물 은 이러한 차이점을 설명합니다.

세션 은 명령을 실행하는 현재 연결을 의미합니다.

범위 는 명령의 즉각적인 컨텍스트를 의미합니다. 모든 저장 프로 시저 호출은 자체 범위에서 실행되고 중첩 된 호출은 호출 프로 시저 범위 내에서 중첩 된 범위에서 실행됩니다. 마찬가지로 응용 프로그램 또는 SSMS에서 실행 된 SQL 명령은 자체 범위에서 실행되며 해당 명령이 트리거를 발생하면 각 트리거는 자체 ​​중첩 범위 내에서 실행됩니다.

따라서 세 가지 신원 검색 방법의 차이점은 다음과 같습니다.

@@identity 세션 에서 생성 된 마지막 아이디 값을 제외한 모든 범위를 반환합니다 .

scope_identity() 세션 과이 범위 에서 생성 된 마지막 ID 값을 반환합니다 .

ident_current()에서 특정 테이블에 대해 생성 된 마지막 ID 값을 반환하는 모든 세션 및 모든 범위를.


11

범위 는 전역 범위와 달리 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 

다른 결과를 제공합니다.


9

@David Freitas가 언급 한 버그와 2012 년에 도입 된 새로운 시퀀스 기능과의 비 호환성 때문에이 세 가지를 멀리하는 것이 좋습니다. 대신 OUTPUT 절을 사용하여 삽입 된 ID 값을 얻을 수 있습니다. 다른 장점은 OUTPUT이 둘 이상의 행을 삽입 한 경우에도 작동한다는 것입니다.

자세한 내용과 예는 여기를 참조하십시오. ID 위기


이 답변에 더 많은 관심이 필요하다고 생각합니다.
cheeze

불행히도 INSERT ... OUTPUT Inserted.xx는 INSERT 트리거와 작동하지 않습니다 (UPDATE ... OUTPUT Updated.xx 및 UPDATE 트리거와 동일). 그들은 INSERT ... OUTPUT INTO를 사용하는 것이 좋지만 너무 장황하며 클라이언트에서 저장 프로 크 대신 사용하는 것이 문제가됩니다. INSERT ... OUTPUT Inserted.xx는 트리거가 필요하지 않은 경우 클라이언트 측 호출과 함께 사용할 때 아름답습니다 (삽입하고 새 행의 자동 생성 된 ID를 반환하려면 ExecuteScalar가 필요합니다).
조지 Birbilis

이 버그가 수정 되었습니까? 기사가 작성된 지 8 년이 지났습니다.
dopatraman

6

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

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

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


4

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

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

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


3

이 책 에서 또 다른 좋은 설명이 있습니다 .

SCOPE_IDENTITY와 @@ IDENTITY의 차이점에 대해 다음 세 개의 명령문으로 스토어드 프로 시저 P1이 있다고 가정하십시오
.-새 ID 값을 생성하는 INSERT-새
프로 시저를 생성하는 INSERT 문이있는 스토어드 프로 시저 P2에 대한 호출 identity
value-함수 SCOPE_IDENTITY 및 @@ IDENTITY를 쿼리하는 문 SCOPE_IDENTITY 함수는 P1 (동일한 세션 및 범위)에서 생성 된 값을 반환합니다. @@ IDENTITY 함수는 P2에 의해 생성 된 값을 반환합니다 (범위에 관계없이 동일한 세션).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.