삽입된 행의 ID를 얻는 가장 좋은 방법은 무엇입니까?
-
09-06-2019 - |
문제
얻는 가장 좋은 방법은 무엇입니까 IDENTITY
삽입된 행의?
나는 ~에 대해 알고 있다 @@IDENTITY
그리고 IDENT_CURRENT
그리고 SCOPE_IDENTITY
그러나 각각에 첨부된 장단점을 이해하지 못합니다.
차이점과 각각을 언제 사용해야 하는지 설명해 주실 수 있나요?
해결책
@@IDENTITY
모든 범위에 걸쳐 현재 세션의 테이블에 대해 생성된 마지막 ID 값을 반환합니다. 여기서 조심해야 해요, 범위에 걸쳐 있기 때문입니다.현재 명령문 대신 트리거에서 값을 얻을 수 있습니다.SCOPE_IDENTITY()
현재 세션 및 현재 범위의 테이블에 대해 생성된 마지막 ID 값을 반환합니다. 일반적으로 사용하려는 것.IDENT_CURRENT('tableName')
모든 세션 및 범위의 특정 테이블에 대해 생성된 마지막 ID 값을 반환합니다.이를 통해 위의 두 테이블이 필요한 테이블이 아닌 경우에 어떤 테이블에서 값을 가져올지 지정할 수 있습니다(매우 드물다).또한 @와 같이가이 스타벅 "레코드를 삽입하지 않은 테이블의 현재 IDENTITY 값을 얻으려는 경우 이 방법을 사용할 수 있습니다."그만큼
OUTPUT
절 ~의INSERT
문을 사용하면 해당 문을 통해 삽입된 모든 행에 액세스할 수 있습니다.특정 문으로 범위가 지정되므로 더 간단하다 위의 다른 기능보다그러나 그것은 조금 더 장황한 (테이블 변수/임시 테이블에 삽입한 다음 이를 쿼리해야 함) 명령문이 롤백되는 오류 시나리오에서도 결과를 제공합니다.즉, 쿼리가 병렬 실행 계획을 사용하는 경우 이는 유일한 보장 방법 정체성을 얻기 위해 (병렬성을 끄는 것보다 부족함)그러나 실행된다 ~ 전에 트리거하며 트리거 생성 값을 반환하는 데 사용할 수 없습니다.
다른 팁
삽입된 ID를 검색하는 가장 안전하고 정확한 방법은 출력 절을 사용하는 것이라고 생각합니다.
예를 들어 (다음에서 가져옴 MSDN 기사)
USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO @MyTableVar
VALUES (N'Operator error', GETDATE());
--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
GO
나도 다른 사람들과 똑같은 말을 하고 있으니 모두가 맞다. 나는 단지 좀 더 명확하게 하려고 노력할 뿐이다.
@@IDENTITY
클라이언트가 데이터베이스에 연결하여 삽입된 마지막 항목의 ID를 반환합니다.
대부분의 경우 이는 잘 작동하지만 때로는 트리거가 발생하여 사용자가 모르는 새 행을 삽입하고 원하는 행 대신 이 새 행에서 ID를 가져옵니다.
SCOPE_IDENTITY()
이 문제를 해결합니다.마지막 항목의 ID를 반환합니다. 당신이 삽입했습니다 SQL 코드에서 너가 보냈다 데이터베이스에.트리거가 추가 행을 생성하는 경우 잘못된 값이 반환되지 않습니다.만세
IDENT_CURRENT
누군가가 삽입한 마지막 ID를 반환합니다.다른 앱이 예상치 못한 시간에 다른 행을 삽입하는 경우 사용자는 자신의 행 대신 해당 행의 ID를 얻게 됩니다.
안전하게 플레이하고 싶다면 항상 사용하세요. SCOPE_IDENTITY()
.붙어 있으면 @@IDENTITY
누군가 나중에 트리거를 추가하기로 결정하면 모든 코드가 손상됩니다.
최고(읽기:가장 안전한) 새로 삽입된 행의 ID를 얻는 방법은 다음을 사용하는 것입니다. output
절:
create table TableWithIdentity
( IdentityColumnName int identity(1, 1) not null primary key,
... )
-- type of this table's column must match the type of the
-- identity column of the table you'll be inserting into
declare @IdentityOutput table ( ID int )
insert TableWithIdentity
( ... )
output inserted.IdentityColumnName into @IdentityOutput
values
( ... )
select @IdentityValue = (select ID from @IdentityOutput)
추가하다
SELECT CAST(scope_identity() AS int);
insert sql 문 끝에
NewId = command.ExecuteScalar()
그것을 되찾을 것이다.
@@IDENTITY, SCOPE_IDENTITY 및 IDENT_CURRENT는 테이블의 IDENTITY 열에 삽입된 마지막 값을 반환한다는 점에서 유사한 함수입니다.
@@IDENTITY 및 SCOPE_IDENTITY는 현재 세션의 테이블에서 생성된 마지막 ID 값을 반환합니다.그러나 SCOPE_IDENTITY는 현재 범위 내의 값만 반환합니다.@@IDENTITY는 특정 범위로 제한되지 않습니다.
IDENT_CURRENT는 범위와 세션에 의해 제한되지 않습니다.지정된 테이블로 제한됩니다.IDENT_CURRENT는 모든 세션 및 범위의 특정 테이블에 대해 생성된 ID 값을 반환합니다.자세한 내용은 IDENT_CURRENT를 참조하세요.
- IDENT_CURRENT 테이블을 인수로 취하는 함수입니다.
- @@신원 테이블에 트리거가 있으면 혼란스러운 결과가 반환될 수 있습니다.
- SCOPE_IDENTITY 대부분의 경우 당신의 영웅입니다.
Entity Framework를 사용하면 내부적으로 OUTPUT
새로 삽입된 ID 값을 반환하는 기술
DECLARE @generated_keys table([Id] uniqueidentifier)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');
SELECT t.[TurboEncabulatorID ]
FROM @generated_keys AS g
JOIN dbo.TurboEncabulators AS t
ON g.Id = t.TurboEncabulatorID
WHERE @@ROWCOUNT > 0
출력 결과는 임시 테이블 변수에 저장되고, 테이블에 다시 조인되며, 테이블에서 행 값을 반환합니다.
메모:EF가 임시 테이블을 다시 실제 테이블에 내부 조인하는 이유를 모르겠습니다(어떤 상황에서 두 테이블이 일치하지 않는지).
하지만 그것이 EF가 하는 일입니다.
이 기술(OUTPUT
)은 SQL Server 2008 이상에서만 사용할 수 있습니다.
@@신원 현재 SQL 연결을 사용하여 삽입된 마지막 ID입니다.이는 새 레코드에 삽입된 ID만 필요하고 나중에 더 많은 행이 추가되었는지 상관하지 않는 삽입 저장 프로시저에서 반환하기에 좋은 값입니다.
SCOPE_IDENTITY 현재 SQL 연결을 사용하여 삽입된 마지막 ID이며 현재 범위에서 즉, 삽입 후 트리거를 기반으로 두 번째 IDENTITY가 삽입된 경우 SCOPE_IDENTITY에는 반영되지 않고 수행한 삽입만 반영됩니다.솔직히 말해서 이것을 사용할 이유가 없었습니다.
IDENT_CURRENT(테이블 이름) 연결이나 범위에 관계없이 삽입된 마지막 ID입니다.레코드를 삽입하지 않은 테이블의 현재 IDENTITY 값을 얻으려는 경우 이를 사용할 수 있습니다.
다른 버전의 SQL Server에서는 말할 수 없지만 2012에서는 직접 출력이 잘 작동합니다.임시 테이블을 사용하여 귀찮게 할 필요가 없습니다.
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)
그런데 이 기술은 여러 행을 삽입할 때도 작동합니다.
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
(...),
(...),
(...)
산출
ID
2
3
4
언제나 scope_identity()를 사용하면 다른 것은 전혀 필요하지 않습니다.
삽입문 뒤에 이것을 추가해야 합니다.그리고 데이터가 삽입되는 테이블 이름을 확인하십시오. 삽입 문에 의해 지금 막 영향을 받은 행이 없는 현재 행을 얻게 됩니다.
IDENT_CURRENT('tableName')
마지막으로 추가/업데이트된 ID를 찾고 계신다면 조금 구식일 수도 있지만 더 정확하게는 이전 PHP 5.5 이전 버전을 사용하는 사람들이 많습니다.자세한 내용은 다음에서 확인할 수 있습니다. http://php.net/manual/en/function.mysql-insert-id.php
$last = mysql_insert_id();
만들기 uuid
열에도 삽입합니다.그러면 uuid로 행을 쉽게 식별할 수 있습니다.