Development Tip

SQL : 방금 삽입 한 값의 ID를 얻는 방법은 무엇입니까?

yourdevel 2020. 10. 18. 19:40
반응형

SQL : 방금 삽입 한 값의 ID를 얻는 방법은 무엇입니까?


테이블에 몇 가지 값을 삽입했습니다. 값이 자동 생성되는 열이 있습니다. 내 코드의 다음 문에서이 값을 검색하고 싶습니다.

올바른 방법으로 수행하는 방법을 알려주시겠습니까?


@@IDENTITY 범위가 안전하지 않으며 원래 테이블에 삽입 트리거가있는 경우 다른 테이블에서 ID를 다시 가져 오며 항상 SCOPE_IDENTITY()


이것이 자동 생성 된 ID로 MSSQL에 대한 저장 프로 시저를 수행하는 방법입니다.

CREATE PROCEDURE [dbo].[InsertProducts]
    @id             INT             = NULL OUT,
    @name           VARCHAR(150)    = NULL,
    @desc           VARCHAR(250)    = NULL

AS

    INSERT INTO dbo.Products
       (Name,
        Description)
    VALUES
       (@name,
        @desc)

    SET @id = SCOPE_IDENTITY();

PHP와 MySQL을 사용하는 경우 방금 삽입 한 항목의 ID를 알려주는 mysql_insert_id () 함수를 사용할 수 있습니다.
하지만 당신의 언어와 DBMS 없이는 여기서 어둠 속에서 촬영하고 있습니다.


이것은 SQL 2005에서 매우 잘 작동합니다.

DECLARE @inserted_ids TABLE ([id] INT);

INSERT INTO [dbo].[some_table] ([col1],[col2],[col3],[col4],[col5],[col6])
OUTPUT INSERTED.[id] INTO @inserted_ids
VALUES (@col1,@col2,@col3,@col4,@col5,@col6)

INSERT 문이 여러 행을 삽입하는 경우 모든 ID를 반환하는 이점이 있습니다.


다시 말하지만 언어에 구애받지 않는 응답은 없지만 Java에서는 다음과 같이 진행됩니다.

Connection conn = Database.getCurrent().getConnection();  
PreparedStatement ps =  conn.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
try {  
    ps.executeUpdate();  
    ResultSet rs = ps.getGeneratedKeys();  
    rs.next();  
    long primaryKey = rs.getLong(1);  
} finally {  
    ps.close();  
}  

Oracle과 함께 작업하는 경우 :

테이블에 삽입 (필드 ....) 값 (값 ...) RETURNING (필드 목록 ...) INTO (변수 ...)

예:

INSERT IN TO PERSON (NAME) VALUES ( 'JACK') RETURNING ID_PERSON INTO vIdPerson

또는 호출하는 경우 ... CallableStatement가있는 Java (sry, 내 분야입니다)

INSERT IN TO PERSON (NAME) VALUES ( 'JACK') RETURNING ID_PERSON INTO?

명령문에 대한 autput 매개 변수 선언


이를 수행하는 표준 방법은 없습니다 (자동 증가 ID를 만드는 표준 방법이없는 것처럼). PostgreSQL에서이를 수행하는 두 가지 방법이 있습니다. 이것이 귀하의 테이블이라고 가정하십시오.

CREATE TABLE mytable (
  id SERIAL PRIMARY KEY,
  lastname VARCHAR NOT NULL,
  firstname VARCHAR
);

동일한 연결에서 연속 된 명령문이면 두 개의 명령문으로 수행 할 수 있습니다 (이는 스크립트가 완료 될 때까지 PHP가 풀에 다시 연결을 제공하지 않기 때문에 연결 풀링을 사용하는 PHP에서 안전합니다).

INSERT INTO mytable (lastname, firstname) VALUES ('Washington', 'George');
SELECT lastval();

lastval () 은 현재 연결에서 사용 된 마지막 자동 생성 시퀀스 값을 제공합니다.

다른 방법은 INSERTPostgreSQL의 RETURNING 절을 사용하는 것입니다.

INSERT INTO mytable (lastname) VALUES ('Cher') RETURNING id;

이 형식은 SELECT처럼 결과 집합 을 반환하며 모든 종류의 계산 된 기본값을 반환하는데도 편리합니다.


중요한 점은 공급 업체 SQL 쿼리를 사용하여 마지막으로 삽입 된 ID를 검색하는 것이 동시 연결에 대한 걱정없이 안전하게 사용할 수 있다는 것입니다.

다른 클라이언트가 삽입 한 ID를 검색하지 않으려면 한 줄을 삽입 한 다음 마지막으로 삽입 된 ID를 선택하려면 트랜잭션을 만들어야한다고 항상 생각했습니다.

그러나 이러한 공급 업체별 쿼리는 항상 데이터베이스에 대한 현재 연결에 대해 마지막으로 삽입 된 ID 검색 합니다 . 이는 자신의 데이터베이스 연결을 사용하는 한 마지막으로 삽입 된 ID가 다른 클라이언트 삽입의 영향을받을 수 없음을 의미합니다.


사이트에서 다음을 발견했습니다.

SQL SERVER – @@ IDENTITY 대 SCOPE_IDENTITY () 대 IDENT_CURRENT – pinaldave에 의해 2007 년 3 월 25 일 레코드의 마지막 삽입 ID 검색

SELECT @@ IDENTITY 값을 생성 한 테이블과 값을 생성 한 문의 범위에 관계없이 연결에서 생성 된 마지막 IDENTITY 값을 반환합니다. @@ IDENTITY는 현재 세션의 테이블에 입력 된 마지막 ID 값을 반환합니다. @@ IDENTITY는 현재 세션으로 제한되지만 현재 범위로 제한되지는 않습니다. 다른 테이블에 ID가 생성되도록하는 테이블에 대한 트리거가있는 경우 해당 ID를 생성 한 트리거 인 경우에도 마지막에 생성 된 ID를 가져옵니다.

SELECT SCOPE_IDENTITY () 값을 생성 한 테이블에 관계없이 동일한 범위의 명령문과 연결에서 생성 된 마지막 IDENTITY 값을 반환합니다. @@ IDENTITY와 마찬가지로 SCOPE_IDENTITY ()는 현재 세션에서 생성 된 마지막 ID 값을 반환하지만 현재 범위로도 제한합니다. 즉, 트리거 또는 사용자 정의 함수에 의해 생성 된 ID가 아니라 명시 적으로 생성 한 마지막 ID 값을 반환합니다.

SELECT IDENT_CURRENT ( 'tablename') 값을 생성 한 연결과 값을 생성 한 문의 범위에 관계없이 테이블에서 생성 된 마지막 IDENTITY 값을 반환합니다. IDENT_CURRENT는 범위와 세션에 의해 제한되지 않습니다. 지정된 테이블로 제한됩니다. IDENT_CURRENT는 모든 세션 및 범위의 특정 테이블에 대해 생성 된 ID 값을 반환합니다.


SQL 2005의 경우 :

다음 테이블 정의를 가정합니다.

CREATE TABLE [dbo].[Test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [somevalue] [nchar](10) NULL,
) 

다음을 사용할 수 있습니다.

INSERT INTO Test(somevalue)
OUTPUT INSERTED.ID
VALUES('asdfasdf')

ID 열의 값을 반환합니다.


@@ IDENTITY는 테이블에서 최근에 추가 된 행의 ID 일 필요는 없지만 현재 연결에 대해 가장 최근에 생성 된 ID를 반환합니다. 최근에 추가 된 행의 ID를 반환하려면 항상 SCOPE_IDENTITY ()를 사용해야합니다.


What database are you using? As far as I'm aware, there is no database agnostic method for doing this.


This is how I've done it using parameterized commands.

MSSQL

 INSERT INTO MyTable (Field1, Field2) VALUES (@Value1, @Value2); 
 SELECT SCOPE_IDENTITY(); 

MySQL

 INSERT INTO MyTable (Field1, Field2) VALUES (?Value1, ?Value2);
 SELECT LAST_INSERT_ID();

sql = "INSERT INTO MyTable (Name) VALUES (@Name);" +
      "SELECT CAST(scope_identity() AS int)";
SqlCommand cmd = new SqlCommand(sql, conn);
int newId = (int)cmd.ExecuteScalar();

Ms SQL Server: this is good solution even if you inserting more rows:

 Declare @tblInsertedId table (Id int not null)

 INSERT INTO Test ([Title], [Text])
 OUTPUT inserted.Id INTO @tblInsertedId (Id)
 SELECT [Title], [Text] FROM AnotherTable

 select Id from @tblInsertedId 

Rob's answer would be the most vendor-agnostic, but if you're using MySQL the safer and correct choise would be the built-in LAST_INSERT_ID() function.


SELECT @@Scope_Identity as Id

There is also @@identity, but if you have a trigger, it will return the results of something that happened during the trigger, where scope_identity respects your scope.


  1. insert the row with a known guid.
  2. fetch the autoId-field with this guid.

This should work with any kind of database.


An Environment Based Oracle Solution:

CREATE OR REPLACE PACKAGE LAST
AS
ID NUMBER;
FUNCTION IDENT RETURN NUMBER;
END;
/

CREATE OR REPLACE PACKAGE BODY LAST
AS
FUNCTION IDENT RETURN NUMBER IS
    BEGIN
    RETURN ID;
    END;
END;
/


CREATE TABLE Test (
       TestID            INTEGER ,
    Field1      int,
    Field2      int
)


CREATE SEQUENCE Test_seq
/
CREATE OR REPLACE TRIGGER Test_itrig
BEFORE INSERT ON Test
FOR EACH ROW
DECLARE
seq_val number;
BEGIN
IF :new.TestID IS NULL THEN
    SELECT Test_seq.nextval INTO seq_val FROM DUAL;
    :new.TestID := seq_val;
    Last.ID := seq_val;
END IF;
END;
/

To get next identity value:
SELECT LAST.IDENT FROM DUAL

In TransactSQL, you can use OUTPUT clause to achieve that.

INSERT INTO my_table(col1,col2,col3) OUTPUT INSERTED.id VALUES('col1Value','col2Value','col3Value')

FRI: http://msdn.microsoft.com/en-us/library/ms177564.aspx


Simplest answer:

command.ExecuteScalar()

by default returns the first column

Return Value Type: System.Object The first column of the first row in the result set, or a null reference (Nothing in Visual Basic) if the result set is empty. Returns a maximum of 2033 characters.

Copied from MSDN

참고URL : https://stackoverflow.com/questions/45651/sql-how-to-get-the-id-of-values-i-just-inserted

반응형