Нахождение следующего доступного идентификатора в MySQL - PullRequest
49 голосов
/ 10 сентября 2009

Мне нужно найти следующий доступный идентификатор (если в базе данных 5 данных, я должен получить следующее доступное место вставки, равное 6) в базе данных MySQL. Как я могу это сделать? Я использовал MAX(id), но когда я удаляю несколько строк из базы данных, он все еще содержит старое максимальное значение, которое он не обновил.

Ответы [ 15 ]

85 голосов
/ 10 сентября 2009

Обновление 2014-12-05: Я не рекомендую этот подход по причинам, изложенным в ответе Саймона (принятом), а также в комментарии Диего. Пожалуйста, используйте запрос ниже на свой страх и риск.

Самый короткий из найденных мной на сайте разработчиков MySQL:

SELECT Auto_increment FROM information_schema.tables WHERE table_name='the_table_you_want'

учтите, что если у вас мало баз данных с одинаковыми таблицами, вы должны также указать имя базы данных, например:

SELECT Auto_increment FROM information_schema.tables WHERE table_name='the_table_you_want' AND table_schema='the_database_you_want';
20 голосов
/ 10 сентября 2009

Не думаю, что вы когда-либо будете уверены в идентификаторе next , потому что кто-то может вставить новую строку сразу после того, как вы запросите следующий идентификатор. Вам, по крайней мере, понадобится транзакция, и если я не ошибаюсь, вы можете получить только действительный идентификатор после его вставки, по крайней мере, это обычный способ обработки - см. http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html

17 голосов
/ 08 июня 2011

В дополнение к ответу Лукаша Лысика - LEFT-JOIN вид SQL.
Как я понимаю, если есть идентификаторы: 1,2,4,5, он должен вернуть 3.

SELECT u.Id + 1 AS FirstAvailableId
FROM users u
LEFT JOIN users u1 ON u1.Id = u.Id + 1
WHERE u1.Id IS NULL
ORDER BY u.Id
LIMIT 0, 1

Надеюсь, это поможет некоторым посетителям, хотя пост довольно старый.

11 голосов
/ 10 сентября 2009

Учитывая то, что вы сказали в комментарии:

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

Есть способ сделать то, что вы просите, а именно: спросить у таблицы, какой идентификатор следующей вставленной строки будет равен , прежде чем вы на самом деле вставите:

SHOW TABLE STATUS WHERE name = "myTable"

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

10 голосов
/ 10 сентября 2009

Как я понимаю, если есть идентификаторы: 1,2,4,5, он должен вернуть 3.

SELECT t1.id + 1
FROM theTable t1
WHERE NOT EXISTS (
    SELECT * 
    FROM theTable t2
    WHERE t2.id = t1.id + 1
)
LIMIT 1
4 голосов
/ 10 сентября 2009

ты сказал:

Мой идентификатор - автоматическое увеличение чтобы получить идентификатор и преобразовать его в другая база. Так что мне нужно получить следующий Идентификатор перед вставкой вызывает преобразованный код тоже будет вставлен.

то, что вы просите, очень опасно и приведет к состоянию гонки. если ваш код запускается дважды одновременно разными пользователями, они оба получат 6, а их обновления или вставки будут перебрасываться друг на друга.

Я предлагаю вам вместо INSERT войти в таблицу, получить значение auto_increment, используя LAST_INSERT_ID(), а затем UPDATE строку, чтобы установить любое имеющееся у вас значение, зависящее от значения auto_increment.

3 голосов
/ 10 сентября 2009

Если вы хотите выбрать первый разрыв, используйте это:

SELECT  @r
FROM    (
        SELECT  @r := MIN(id) - 1
        FROM    t_source2
        ) vars,
        t_source2
WHERE   (@r := @r + 1) <> id
ORDER BY
        id
LIMIT   1;

Существует синтаксическая версия того же запроса ANSI:

SELECT  id
FROM    mytable mo
WHERE   (
        SELECT  id + 1
        FROM    mytable mi
        WHERE   mi.id < mo.id
        ORDER BY
                mi.id DESC
        LIMIT 1
        ) <> id
ORDER BY
        id,
LIMIT   1

однако, это будет медленно из-за ошибки оптимизатора в MySQL.

1 голос
/ 04 ноября 2015

Слишком поздно ответить на этот вопрос сейчас, но надеюсь, что это кому-нибудь поможет.

@ Eimantas уже дал лучший ответ, но решение не сработает, если у вас есть две или более таблицы с одинаковыми именами на одном сервере.

Я немного изменил ответ @ Eimantas для решения вышеуказанной проблемы.

select Auto_increment as id from information_schema.tables where table_name = 'table_name' and table_schema = 'database_name'
1 голос
/ 10 сентября 2009

Если вы действительно хотите вычислить ключ следующей вставки перед вставкой строки (что, на мой взгляд, не очень хорошая идея), то я бы посоветовал вам использовать максимально используемый в настоящее время идентификатор плюс один:

SELECT MAX(id) + 1 FROM table

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

INSERT INTO table (col1) VALUES ("Text");
SELECT LAST_INSERT_ID();

Возвращаемый набор теперь содержит только один столбец, который содержит идентификатор вновь созданной строки.

0 голосов
/ 09 марта 2017
<?php
Class Database{
    public $db;
    public $host   = DB_HOST;
    public $user   = DB_USER;
    public $pass   = DB_PASS;
    public $dbname = DB_NAME;

    public $link;
    public $error;

    public function __construct(){
        $this->connectDB();
    }
    private function connectDB(){
    $this->link = new mysqli($this->host, $this->user, $this->pass, $this->dbname);
    if(!$this->link){
        $this->error ="Connection fail".$this->link->connect_error;
        return false;
    }
 }

    // Select or Read data

    public function select($query){
        $result = $this->link->query($query) or die($this->link->error.__LINE__);
        if($result->num_rows > 0){
            return $result;
        } else {
            return false;
        }
    }

}
 $db = new Database();
$query = "SELECT * FROM table_name WHERE id > '$current_postid' ORDER BY ID ASC LIMIT 1";
$postid = $db->select($query);
if ($postid) {
  while ($result = $postid->fetch_assoc()) { 
        echo $result['id'];
    } 

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