SQL: Як отримати ідентифікатор значень, які я щойно вставив?


76

Я вставив деякі значення в таблицю. Є стовпець, значення якого генерується автоматично. У наступному викладі мого коду я хочу отримати це значення.

Чи можете ви сказати мені, як це зробити правильно?


6
Це допоможе, якщо ви дасте детальну інформацію про те, яку базу даних ви використовуєте, оскільки методи відрізняються.
Дауст,

Відповіді:


57

@@IDENTITY не є безпечним для області та поверне вам ідентифікатор з іншої таблиці, якщо у вас є тригер вставки в вихідній таблиці, завжди використовуйте SCOPE_IDENTITY()


2
є відомі помилки з SCOPE_IDENTITY () у sql server 2005, не впевнений у 2008 році, речення OUTPUT може повернути набір ідентифікаторів, якщо потрібно
KM.

1
відома помилка з SCOPE_IDENTITY (), що повертає неправильні значення: blog.sqlauthority.com/2009/03/24/…, навколо цього - не запускати INSERT у багатопроцесорному паралельному плані або використовувати речення OUTPUT
KM.

4
URL-адреса обрізана на коментар @KM. тому, сподіваємось, це посилання працює: SCOPE_IDENTITY Помилка з паралельним планом та рішенням
багатопроцесорних процесів

29

Ось як я виконую свої процедури зберігання для 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();

14

Якщо ви використовуєте PHP та MySQL, ви можете скористатися функцією mysql_insert_id (), яка повідомляє вам ідентифікатор елемента, до якого ви щойно звернулись.
Але без вашої мови та СУБД я тут просто знімаю в темряві.


14

Це дуже добре працює в 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 вставляє кілька рядків.


11

Знову ж ніякої мовної агностичної відповіді, але в 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();  
}  

Приємно, я просто шукав цього
raupach

8

Якщо ви працюєте з Oracle:

Вставка значень таблиці (поля ....) (значення ...) ПОВЕРНЕННЯ (список полів ...) В (змінні ...)

приклад:

ВСТАВИТИ В ЗНАЧЕННЯ ОСОБИ (ІМ'Я) ('JACK') ПОВЕРНЕННЯ ID_PERSON У VIdPerson

або якщо ви телефонуєте з ... Java із CallableStatement (о, це моє поле)

ВСТАВИТИ В ЗНАЧЕННЯ ОСОБИ (ІМ'Я) ('JACK') ПОВЕРНЕННЯ ІДЕНТИФІКАЦІЇ ОСОБИ?

і оголошення параметра введення для виписки


6

Немає стандартного способу зробити це (як не існує стандартного способу створення ідентифікаторів з автоматичним збільшенням). Ось два способи зробити це в 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 () дає вам останнє автоматично згенероване значення послідовності, що використовується у поточному з'єднанні.

Інший спосіб полягає у використанні речення PostgreSQL RETURNING в інструкції INSERT :

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

Ця форма повертає набір результатів так само, як оператор SELECT , а також зручна для повернення будь-якого обчисленого значення за замовчуванням.


цей ідентифікатор, що повертається, дасть право Resultset Object для Java?
Анкур Лорія,

4

Важливим зауваженням є те, що використання SQL-запитів постачальника для отримання останнього вставленого ідентифікатора безпечно використовувати, не побоюючись паралельних з'єднань.

Я завжди думав, що вам потрібно створити транзакцію, щоб ВСТАВИТИ рядок, а потім ВИБРАТИ останній вставлений ідентифікатор, щоб уникнути отримання ідентифікатора, вставленого іншим клієнтом.

Але ці запити конкретного постачальника завжди отримують останній вставлений ідентифікатор поточного підключення до бази даних . Це означає, що на останній вставлений ідентифікатор не можуть впливати інші вставки клієнта, якщо вони використовують своє власне підключення до бази даних.


4

Для 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.


Це все ще чудово працює в нових версіях SQL Server.
dub stylee

4

З сайту я дізнався такі речі:

SQL SERVER - @@ IDENTITY vs SCOPE_IDENTITY () vs IDENT_CURRENT - Отримати останню вставку ідентифікаційного запису 25 березня 2007 р. Від pinaldave

SELECT @@ IDENTITY Він повертає останнє значення IDENTITY, створене у з'єднанні, незалежно від таблиці, яка створила значення, і незалежно від обсягу оператора, що створив значення. @@ IDENTITY поверне останнє значення ідентичності, введене до таблиці у вашому поточному сеансі. Хоча @@ IDENTITY обмежується поточним сеансом, він не обмежується поточним обсягом. Якщо у вас є тригер в таблиці, який викликає створення ідентичності в іншій таблиці, ви отримаєте ідентичність, яка була створена останньою, навіть якщо це був тригер, який її створив.

SELECT SCOPE_IDENTITY () Він повертає останнє значення IDENTITY, створене для з'єднання та за допомогою оператора в одному і тому ж обсязі, незалежно від таблиці, яка створила значення. SCOPE_IDENTITY (), як @@ IDENTITY, поверне останнє значення ідентичності, створене в поточному сеансі, але також обмежить його вашим поточним обсягом. Іншими словами, він поверне останнє значення ідентичності, яке ви явно створили, а не будь-яке посвідчення, створене тригером або визначеною користувачем функцією.

SELECT IDENT_CURRENT ('ім'я таблиці') Він повертає останнє значення IDENTITY, створене в таблиці, незалежно від з'єднання, яке створило значення, і незалежно від обсягу оператора, що створив значення. IDENT_CURRENT не обмежується обсягом та сеансом; він обмежений вказаною таблицею. IDENT_CURRENT повертає значення ідентичності, створене для певної таблиці в будь-якому сеансі та будь-якій області.


Дякуємо, що пояснили це!
дуг

2

Пам'ятайте, що @@ IDENTITY повертає останню створену ідентифікацію для вашого поточного з'єднання, не обов'язково ідентичність для нещодавно доданого рядка в таблиці. Ви завжди повинні використовувати SCOPE_IDENTITY (), щоб повернути ідентифікатор нещодавно доданого рядка.


2

Яку базу даних ви використовуєте? Наскільки мені відомо, для цього не існує методу агностики бази даних.


2

Ось як я це робив, використовуючи параметризовані команди.

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();

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

2

Пані SQL Server: це хороше рішення, навіть якщо ви вставляєте більше рядків:

 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 

1

Відповідь Роба була б найбільш агностичною для продавців, але якщо ви використовуєте MySQL, то вбудованою LAST_INSERT_ID()функцією буде більш безпечний та правильний вибір .


0
SELECT @@Scope_Identity as Id

Існує також ідентичність @@, але якщо у вас є тригер, він поверне результати чогось, що сталося під час тригера, де scope_identity поважає вашу область.


0
  1. вставити рядок із відомим посібником.
  2. отримати поле autoId за допомогою цього посібника.

Це має працювати з будь-якою базою даних.


0

Рішення Oracle на основі середовища:

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


0

Найпростіша відповідь:

command.ExecuteScalar()

за замовчуванням повертає перший стовпець

Тип значення, що повертається: System.Object Перший стовпець першого рядка в наборі результатів або нульове посилання (у Visual Basic немає нічого), якщо набір результатів порожній. Повертає максимум 2033 символи.

Скопійовано з MSDN

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.