Получить новый идентификатор первичного ключа записи из запроса вставки MySQL?


250

Итак, допустим, я делаю mysql INSERTв одну из моих таблиц, и в таблице есть столбец, item_idкоторый установлен в autoincrementи primary key.

Как получить запрос на вывод значения вновь созданного первичного ключа item_idв том же запросе?

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

Если это невозможно, то каков наилучший способ обеспечить получение правильного идентификатора?


1
Нет способа вернуть что-либо из такого INSERTзапроса; почему вы думаете, что это может дать неправильный результат?
Взрыв таблетки

4
Что ж, если процесс выполняется двумя людьми отдельно, я думаю, вы могли бы получить перекрывающийся список процессов - поскольку вам нужно выполнить 2 отдельных запроса?
Эми Невилл


@JimFell да, это в основном тот же вопрос, но у него в целом ответы гораздо лучше
RozzA

1
Используйте postgresql, затем сделайте так, как эта таблица INSERT INTO (col1, col2) VALUES (val1, val2) RETURNING id или таблица INSERT INTO (col1, col2) VALUES (val1, val2) RETURNING * или таблица UPDATE SET col1 = val1, col2 = val2 Идентификатор оператора WHERE RETURNING или таблица UPDATE SET (col1, col2) = (val1, val2) Идентификатор оператора WHERE RETURNING или таблица SET UPDATE (col1, col2) = (val1, val2) Оператор WHERE RETURNING *
gdarcan

Ответы:


328

Вам необходимо использовать LAST_INSERT_ID()функцию: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

Например:

INSERT INTO table_name (col1, col2,...) VALUES ('val1', 'val2'...);
SELECT LAST_INSERT_ID();

Это вернет вам PRIMARY KEYзначение последней строки, которую вы вставили:

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

Таким образом, значение, возвращаемое для LAST_INSERT_ID()каждого пользователя, не зависит от других запросов, которые могут выполняться на сервере от других пользователей .


8
да, но что, если в промежутке (между запросами в списке процессов) была вставлена ​​какая-то другая строка? Есть ли способ написать запрос на вставку, чтобы он выводил это?
Эми Невилл

Хорошо, я вижу ... последний идентификатор вставки запроса записывается, даже если он не зарегистрирован в результате ... $ mysqli-> insert_id
Эми Невилл,

28
Это вернет вам PRIMARY KEYзначение последней строки, которую вы вставили, потому что это для каждого соединения - каждое соединение с сервером будет сохранять для этого свое значение. Я обновил ответ, чтобы уточнить это.
Дункан Лок

Итак, предположим, что 3 пользователя одновременно разместили свои формы, и моя база данных должна их ввести. Я хочу добавить строку, соответствующую каждому вновь созданному идентификатору table1 в table2. Заботится ли параллелизм или мне придется делать это вручную в PHP для входящих запросов на запись в базу данных?
bad_keypoints

Если в момент, когда вы выполняете вставку table1, база данных знает всю информацию, которую вы хотите вставить в table2, вы можете использовать триггер для этого или объединить это в запрос. Если нет, то вам нужно использовать несколько запросов - то есть делать это в PHP. Это зависит от того, что это за данные и откуда они поступают для второй вставки.
Дункан Лок

22

BEWARE !! "LAST_INSERT_ID ()", если вы пытаетесь вернуть значение этого первичного ключа в PHP.

Я знаю, что этот поток не помечен как php, но для всех, кто сталкивался с этим ответом и хочет вернуть идентификатор вставки MySQL из вставки с PHP-скриптом, используя стандартные вызовы mysql_query - он не будет работать и не будет очевиден без регистрации ошибок SQL.

Более новый mysqli поддерживает несколько запросов - который LAST_INSERT_ID () на самом деле является вторым запросом от оригинала.

IMO, отдельный SELECT для идентификации последнего первичного ключа безопаснее, чем дополнительная функция mysql_insert_id (), возвращающая идентификатор AUTO_INCREMENT, сгенерированный из предыдущей операции INSERT.


7
LAST_INSERT_IDявляется функцией MySQL для каждого соединения Если вы запросите последний идентификатор вставки, возможно, отдельное соединение выполнит запись, и у вас будет неправильный идентификатор.
Таблетки взрыва

@ExplosionPills mysql_insert_id()также работает для каждого отдельного соединения, но также страдает странным поведением, как показано здесь stackoverflow.com/a/897374/1305910 в комментарии Cliffordlife - не говоря уже о том, что мы все должны были использоватьmysqli
RozzA

Можете ли вы уточнить, что вы имеете в виду, когда вы остаетесь «это не будет работать»?
Джон Ктеджик

18

Из LAST_INSERT_ID()документации:

Сгенерированный идентификатор поддерживается на сервере для каждого подключения

То есть, если у вас есть два отдельных запроса к сценарию одновременно, они не будут влиять друг на друга LAST_INSERT_ID()(если, возможно, вы не используете постоянное соединение).


2
Я думаю, что сомнительно, если в вашей таблице есть триггер, который выполняет вставку в другую таблицу ... LAST_INSERT_ID () вернет значение идентификатора другой таблицы ...
bgies,

15

Вот что вы ищете !!!

select LAST_INSERT_ID()

Это лучшая альтернатива SCOPE_IDENTITY()функции, используемой в SQL Server.

Вам также нужно помнить, что это будет работать только в том случае, если Last_INSERT_ID()по вашему Insertзапросу запущено. То есть запрос возвращает идентификатор, вставленный в схему. Вы не можете получить последний вставленный идентификатор конкретной таблицы.

Для получения более подробной информации перейдите по ссылке Эквивалентная функция SQLServer SCOPE_IDENTITY () в MySQL?


6

Если вам нужно значение перед вставкой строки:

CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
    RETURNS BIGINT
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

    DECLARE Value BIGINT;

    SELECT
        AUTO_INCREMENT INTO Value
    FROM
        information_schema.tables
    WHERE
        table_name = TableName AND
        table_schema = DATABASE();

    RETURN Value;

END

Вы можете использовать это во вставке:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);

1
Эта не кажется хорошей идеей? Если 2 клиента вызывают эту функцию одновременно, они подумают, что вставляют один и тот же идентификатор, когда на самом деле это не так ... один будет немного медленнее при вставке и получит следующий идентификатор, не зная об этом.
CarCar

5

Вы получите эти параметры в результате запроса:

    "fieldCount": 0,
    "affectedRows": 1,
    "insertId": 66,
    "serverStatus": 2,
    "warningCount": 1,
    "message": "",
    "protocol41": true,
    "changedRows": 0

Это insertIdименно то, что вам нужно.

(NodeJS-MySql)


4

Если в python используется pymysql, из курсора вы можете использовать cursor.lastrowid


2

просто используйте "$ last_id = mysqli_insert_id ($ conn);"


2
Я действительно споткнулся здесь в поисках php-версии этого ответа благодаря Google, поэтому я проголосовал за этот ответ. Хотя технически OP не просил php, это может быть полезно для многих людей, которые также спотыкаются здесь.
фотограф Бритт

Большое спасибо, Арнав! Я
Хуан Седано

1

Если вы используете PHP: На объекте PDO вы можете просто вызвать метод lastInsertId после вставки.

В противном случае с LAST_INSERT_ID вы можете получить значение, подобное этому:SELECT LAST_INSERT_ID();



0

Я просто хочу поделиться своим подходом к этому в PHP, некоторые из вас могут найти его неэффективным способом, но это на 100 лучше, чем другие доступные варианты.

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

Это помогает защитить строку и получить правильный первичный ключ.

Я действительно не рекомендую это, если у вас нет других вариантов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.