SQL: Как получить идентификатор значений, которые я только что вставил? - PullRequest
75 голосов
/ 05 сентября 2008

Я вставил некоторые значения в таблицу. Существует столбец, значение которого генерируется автоматически. В следующем утверждении моего кода я хочу получить это значение.

Можете ли вы сказать мне, как это сделать правильно?

Ответы [ 21 ]

56 голосов
/ 05 сентября 2008

@@IDENTITY не является безопасным для объема и вернет вам идентификатор из другой таблицы, если у вас есть триггер вставки в исходную таблицу, всегда используйте SCOPE_IDENTITY()

29 голосов
/ 05 сентября 2008

Так я делаю свои процедуры хранения для 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 голосов
/ 05 сентября 2008

Если вы используете PHP и MySQL, вы можете использовать функцию mysql_insert_id (), которая сообщит вам идентификатор элемента, который вы только что добавили.
Но без вашего языка и СУБД я просто стреляю в темноте.

14 голосов
/ 23 ноября 2008

Это очень хорошо работает в 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 голосов
/ 05 сентября 2008

Опять же, не зависит от языка, но в 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();  
}  
8 голосов
/ 05 сентября 2008

Если вы работаете с Oracle:

Вставка в таблицу (поля ....) значений (значения ...) ВОЗВРАТ (список полей ...) INTO (переменные ...)

пример:

ВСТАВИТЬ В ЧЕЛОВЕКА (ИМЯ) ЗНАЧЕНИЯ ('ДЖЕК') ВЕРНУТЬСЯ ID_PERSON INTO vIdPerson

или если вы звоните из ... Java с CallableStatement (sry, это мое поле)

ВСТАВИТЬ В ЧЕЛОВЕКА (ИМЯ) ЗНАЧЕНИЯ ('ДЖЕК') ВЕРНУТЬСЯ ID_PERSON INTO?

и объявление параметра autput для оператора

6 голосов
/ 05 сентября 2008

Нет стандартного способа сделать это (так же, как нет стандартного способа создания автоматически увеличивающихся идентификаторов). Вот два способа сделать это в 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 () дает вам последнее автоматически сгенерированное значение последовательности, используемое в текущем соединении.

Другой способ - использовать предложение RETURNING в PostgreSQL для оператора INSERT :

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

Эта форма возвращает набор результатов точно так же, как оператор SELECT , и также удобна для возврата любого вида вычисленного значения по умолчанию.

4 голосов
/ 05 сентября 2008

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

Я всегда думал, что вам нужно создать транзакцию, чтобы ВСТАВИТЬ строку, а затем ВЫБРАТЬ последний вставленный идентификатор, чтобы избежать получения идентификатора, вставленного другим клиентом.

Но эти специфические запросы поставщиков всегда извлекают последний вставленный идентификатор для текущего подключения к базе данных . Это означает, что другие вставленные идентификаторы не могут быть затронуты другими вставками клиента, если они используют собственное соединение с базой данных.

4 голосов
/ 01 октября 2010

С сайта я узнал следующие вещи:

SQL SERVER - @@ IDENTITY vs SCOPE_IDENTITY () vs IDENT_CURRENT - получить последнюю вставленную личность записи 25 марта 2007 года от pinaldave

ВЫБЕРИТЕ @@ IDENTITY Он возвращает последнее значение IDENTITY, созданное для соединения, независимо от таблицы, которая произвела значение, и независимо от области действия оператора, который произвел значение. @@ IDENTITY вернет последнее значение идентификатора, введенное в таблицу в текущем сеансе. Хотя @@ IDENTITY ограничено текущим сеансом, оно не ограничено текущей областью. Если у вас есть триггер в таблице, который вызывает создание идентификатора в другой таблице, вы получите идентификатор, который был создан последним, даже если это был триггер, который его создал.

SELECT SCOPE_IDENTITY () Он возвращает последнее значение IDENTITY, созданное для соединения и с помощью оператора в той же области, независимо от таблицы, которая произвела значение. SCOPE_IDENTITY (), подобно @@ IDENTITY, вернет последнее значение идентификатора, созданное в текущем сеансе, но также ограничит его текущей областью. Другими словами, он вернет последнее значение идентификатора, которое вы явно создали, а не любое значение, созданное триггером или определенной пользователем функцией.

SELECT IDENT_CURRENT («имя таблицы») Он возвращает последнее значение IDENTITY, созданное в таблице, независимо от соединения, создавшего это значение, и независимо от области действия оператора, создавшего это значение. IDENT_CURRENT не ограничен областью действия и сессией; он ограничен указанной таблицей. IDENT_CURRENT возвращает значение идентификатора, созданное для конкретной таблицы в любом сеансе и любой области.

3 голосов
/ 05 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...