Jak uzyskać następny identyfikator automatycznego zwiększania w mysql


114

Jak zdobyć następny identyfikator w mysql, aby wstawić go do tabeli

INSERT INTO payments (date, item, method, payment_code)
VALUES (NOW(), '1 Month', 'paypal', CONCAT("sahf4d2fdd45", id))

1
użyj auto_incrementkolumny
knittl

Chcesz następny identyfikator, czy identyfikator wiersza, który aktualnie wstawiasz? To znaczy, czy identyfikator na końcu kodu płatności powinien być identyfikatorem wiersza, w którym przechowywany jest kod płatności?
Mike,

id wiersza, który aktualnie
wstawiam

6
W takim przypadku połącz wartości podczas ich pobierania, a nie wstawiania. Jest to o wiele łatwiejsze i wykluczasz otrzymanie niewłaściwego identyfikatora lub konieczność uruchomienia aktualizacji - pomyśl, co by się stało, gdyby wiersz, który właśnie wstawiłeś, zostałby zażądany przez innego klienta, zanim aktualizacja miałaby szansę zostać uruchomiona: klient skończy się z nieprawidłowym kodem płatności. W systemie o małym natężeniu ruchu może się to nie zdarzyć, ale nie widzę sensu podejmowania ryzyka.
Mike,

... lub jak wskazuje @binaryLV, blokowanie zasobów może również rozwiązać problem. Zobacz: dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Mike

Odpowiedzi:


12

Użyj LAST_INSERT_ID()z zapytania SQL.

Lub

Możesz również użyć, mysql_insert_id()aby uzyskać go za pomocą PHP.


13
@Sarfraz: Pytanie było o NEXT id nie LAST jak powiedział pan wspomnieć LAST_INSERT_ID().
Felipe Pereira,

1
Jeśli wiersze zostaną usunięte w tabeli, wartość maksymalna będzie błędna
peterchaula

tylko uwaga z '17 - funkcje mysql * są przestarzałe - powyżej można zrobić za pomocąmysqli_insert_id
treyBake

kto oznaczył to jako odpowiedź? pytanie dotyczy następnego insertu, a nie ostatniego.
Amit Shah

253

Możesz użyć

SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'table_name'
AND table_schema = DATABASE( ) ;

lub jeśli nie chcesz używać schematu information_schema, możesz użyć tego

SHOW TABLE STATUS LIKE 'table_name'

Dzięki za dwie pierwsze opcje ... Ale trzecia to tylko numer dwa wywołany z PHP .. Nie jestem pewien, co sprawia, że ​​jest to szybsze na dużych bazach danych ...
Gerard ONeill

1
@GerardONeill Usunięto to
ravi404

3
ponieważ pamięć podręczna jest używana do pobierania danych z information_schema.tables, to rozwiązanie nie działa już dla mysql 8.
Bruno,

1
@Bruno, czy możesz zamieścić referencje?
mvorisek

1
Ten oficjalny dokument stwierdza, że TABLES.AUTO_INCREMENTjest buforowany dev.mysql.com/doc/refman/8.0/en/… . Blog MySQL również zawiera kilka postów na ten temat, ale zmienna systemowa, o której wspominają, wydaje się przestarzała: mysqlserverteam.com/… mysqlserverteam.com/…
Bruno

50

Możesz uzyskać następną wartość automatycznego zwiększania, wykonując:

SHOW TABLE STATUS FROM tablename LIKE Auto_increment
/*or*/
SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = 'tablename'

Należy pamiętać, że należy nie używać tego zmienić tabelę, należy użyć kolumny auto_increment to zrobić automatycznie zamiast.
Problem polega na tym, że last_insert_id()jest to retrospektywne i dzięki temu można je zagwarantować w ramach bieżącego połączenia.
To dziecko jest perspektywiczne i dlatego nie jest wyjątkowe pod względem połączenia i nie można na nim polegać.
To działałoby tylko w przypadku jednej bazy danych połączeń, ale bazy danych z jednym połączeniem mają dziś zwyczaj stawania się jutro wieloma bazami danych połączeń.

Widzieć: SHOW TABLE STATUS


5
Nie odrzuciłem tego, ale problem z próbą użycia ostatniej wartości autoinkrementacji polega na tym, że może nie być ostatnią, zanim zaczniesz jej używać - bez względu na to, jak szybko zostanie wykonany SELECT i późniejszy WSTAW.
Mike,

@Mike, a co, jeśli zostanie to zrobione w jednym zapytaniu? Coś jak insert into table_name (field1, field2) select 'constant', auto_increment from information_schema.tables where table_name = 'table_name'? after insertlast_insert_id()
Użyłbym

1
@binaryLV: Im mniejsza przerwa między SELECT i INSERT, tym mniejsza szansa, że ​​wartość ulegnie zmianie, ale nie wyklucza tego całkowicie. Wyobraź sobie system z tysiącami trafień w bazie danych na minutę - szanse na zmianę wartości dramatycznie wzrosną. Blokowanie tabeli lub wiersza może temu zapobiec, jeśli jest wykonywane jako pojedyncze zapytanie, ale jest to zależne od określonego zachowania silnika bazy danych, które może nie być dobrze udokumentowane. Poszedłbym z kolejnym, UPDATEgdybym też. Ale wolałbym po prostu połączyć te dwie rzeczy w czasie wyświetlania i zaoszczędzić wszystkich kłopotów.
Mike,

3
SHOW TABLE STATUSspodziewa się zobaczyć database namepo FROMi 'table name pattern'po LIKE.
x-yuri

2
ponieważ pamięć podręczna jest używana do pobierania danych z information_schema.tables, to rozwiązanie nie działa już dla mysql 8.
Bruno,

15

To zwróci wartość automatycznego przyrostu dla bazy danych MySQL, a ja nie sprawdzałem tego z innymi bazami danych. Pamiętaj, że jeśli używasz innej bazy danych, składnia zapytania może być inna.

SELECT AUTO_INCREMENT 
FROM information_schema.tables
WHERE table_name = 'your_table_name'
     and table_schema = 'your_database_name';

SELECT AUTO_INCREMENT 
FROM information_schema.tables
WHERE table_name = 'your_table_name'
     and table_schema = database();

SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name = 'twoja_nazwa_tabeli' i table_schema = 'twoja_nazwa_bazy_danych';
LJay

10

Najlepsza odpowiedź wykorzystuje PHP MySQL_ jako rozwiązanie, pomyślałem, że udostępnię zaktualizowane rozwiązanie PHP MySQLi_ , aby to osiągnąć. W tym przykładzie nie ma wyjścia błędu!

$db = new mysqli('localhost', 'user', 'pass', 'database');
$sql = "SHOW TABLE STATUS LIKE 'table'";
$result=$db->query($sql);
$row = $result->fetch_assoc();

echo $row['Auto_increment'];

Wyrzuca następny automatyczny przyrost w tabeli.


ponieważ pamięć podręczna jest używana do pobierania danych z information_schema.tables, to rozwiązanie nie działa już dla mysql 8.
Bruno,

9

W PHP możesz spróbować tego:

$query = mysql_query("SELECT MAX(id) FROM `your_table_name`");
$results = mysql_fetch_array($query);
$cur_auto_id = $results['MAX(id)'] + 1;

LUB

$result = mysql_query("SHOW TABLE STATUS WHERE `Name` = 'your_table_name'");
$data = mysql_fetch_assoc($result);
$next_increment = $data['Auto_increment'];

5
Pamiętaj, że w przypadku pierwszej metody, jeśli rekord o najwyższym identyfikatorze zostanie usunięty, utworzysz nowy rekord z identyfikatorem, który poprzednio miał porzucony.
Tom Jenkinson

a jeśli poprzedni klucz był używany w innych tabelach i nadal jest tam przechowywany, możesz skończyć z bardzo dziwną magią
Tebe

pierwszy zwraca zły identyfikator, jeśli upuścisz ostatnio wstawiony rekord,
Ali Parsa,

6

Rozwiązanie:

CREATE TRIGGER `IdTrigger` BEFORE INSERT ON `payments`
  FOR EACH ROW
BEGIN

SELECT  AUTO_INCREMENT Into @xId
    FROM information_schema.tables
    WHERE 
    Table_SCHEMA ="DataBaseName" AND
    table_name = "payments";

SET NEW.`payment_code` = CONCAT("sahf4d2fdd45",@xId);

END;

„DataBaseName” to nazwa naszej bazy danych


5

Wystarczy proste zapytanie SHOW TABLE STATUS LIKE 'table_name'



3

Nie możesz używać identyfikatora podczas wstawiania, ani go nie potrzebujesz. MySQL nawet nie zna identyfikatora podczas wstawiania tego rekordu. Możesz po prostu zapisać "sahf4d2fdd45"w payment_codetabeli i użyć idipayment_code później.

Jeśli naprawdę potrzebujesz, aby kod payment_code zawierał identyfikator, ZAKTUALIZUJ wiersz po wstawce, aby dodać identyfikator.


+1 Aby było to trochę bardziej wyraźne: jeśli pobierzesz „najnowszą” wartość z kolumny, gwarantuje się, że będzie ona najnowszą wartością dokładnie w momencie jej pobrania. Może to nie być ostatnia wartość, gdy zaczniesz używać tej wartości w kolejnej wkładce. W przypadku kolumny z automatycznym zwiększaniem zawsze istnieje szansa, że ​​między momentem pobrania identyfikatora a wstawieniem go w innym miejscu została dodana inna wartość. Jeśli odwołujesz się do wiersza, który właśnie wstawiłeś, użycie LAST_INSERT_ID () jest w porządku. Jeśli chcesz zapewnić unikalną wartość, tak nie jest.
Mike,

@cularis, MySQL zna następny identyfikator auto_increment, jest wymieniony w information_schema.tablestabeli.
Johan,

1
@faressoft: Jeśli chodzi o to, aby kod płatności składał się z unikalnego ciągu znaków oraz identyfikatora wiersza zawierającego ten kod płatności, po prostu połącz te dwa elementy podczas pobierania wiersza - za pomocą znaku SELECT ... CONCAT(payment_code, id)lub w kodzie aplikacji. Możesz nawet zawinąć SELECTw a VIEW, aby zawsze zwracać właściwą wartość, bez martwienia się o CONCAT w każdym SELECT z Twojej aplikacji.
Mike,

3

Do czego potrzebny jest następny przyrostowy identyfikator?

MySQL dopuszcza tylko jedno pole autoinkrementacji na tabelę i musi być również kluczem podstawowym, aby zagwarantować unikalność.

Zwróć uwagę, że kiedy otrzymasz następny identyfikator insertu, może on nie być dostępny, gdy go używasz, ponieważ wartość, którą posiadasz, mieści się tylko w zakresie tej transakcji. Dlatego w zależności od obciążenia bazy danych ta wartość może być już wykorzystana w momencie nadejścia następnego żądania.

Sugerowałbym, abyś przejrzał swój projekt, aby upewnić się, że nie musisz wiedzieć, która wartość automatycznego przyrostu ma zostać przypisana jako następna


Nie jest dobrym pomysłem zakładanie rodzaju aplikacji, która wymaga identyfikatora. Istnieją aplikacje, takie jak ta, nad którą obecnie pracuję, które wymagają kolejnego przyrostowego identyfikatora, a pobrana wartość nie jest zagrożona przypisaniem do innego skryptu.
JG Estiot

3

Proponuję przemyśleć to, co robisz. Nigdy nie doświadczyłem ani jednego przypadku użycia, w którym ta specjalna wiedza byłaby wymagana. Następny identyfikator to bardzo szczególny szczegół implementacji i nie liczyłbym na to, że jest bezpieczny dla ACID.

Wykonaj jedną prostą transakcję, która zaktualizuje wstawiony wiersz o ostatni identyfikator:

BEGIN;

INSERT INTO payments (date, item, method)
     VALUES (NOW(), '1 Month', 'paypal');

UPDATE payments SET payment_code = CONCAT("sahf4d2fdd45", LAST_INSERT_ID())
     WHERE id = LAST_INSERT_ID();

COMMIT;

Mogę powiedzieć jeden taki przypadek użycia, próbuję zdiagnozować problem produkcyjny, więc muszę się dowiedzieć, czy ostatni wiersz w tabeli jest tak naprawdę ostatnim wierszem, czy też został dodany po tym, który jakoś został usunięty, tabela zawiera pole auto_increment, więc znajdując te informacje, mogę stwierdzić, czy wiersz został usunięty, czy nigdy nie został dodany.
Usman

1
To może zadziałać dla Ciebie, ale nie polegałbym na tym, ponieważ nie sądzę, że masz na to jakąkolwiek gwarancję: dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html ” gdy kolumna AUTO_INCREMENT jest częścią indeksu z wieloma kolumnami), wartości AUTO_INCREMENT są ponownie używane, jeśli usuniesz wiersz z największą wartością AUTO_INCREMENT w dowolnej grupie. "
Markus Malkusch,

Dzięki, przydatne informacje, również zgodnie z udostępnionym linkiem auto_increment można zresetować ręcznie, wprowadzając liczbę, więc tak nie jest wiarygodne.
Usman

2

Musisz połączyć się z MySQL i wybrać bazę danych, zanim będziesz mógł to zrobić

$table_name = "myTable"; 
$query = mysql_query("SHOW TABLE STATUS WHERE name='$table_name'"); 
$row = mysql_fetch_array($query); 
$next_inc_value = $row["AUTO_INCREMENT"];  

2

użyj „mysql_insert_id ()”. mysql_insert_id () działa na ostatnio wykonanym zapytaniu, pamiętaj, aby wywołać mysql_insert_id () natychmiast po zapytaniu, które generuje wartość.

Poniżej przykład zastosowania:

<?php
    $link = mysql_connect('localhost', 'username', 'password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');

mysql_query("INSERT INTO mytable  VALUES('','value')");
printf("Last inserted record has id %d\n", mysql_insert_id());
    ?>

Mam nadzieję, że powyższy przykład się przyda.


Dzięki, wiem o tym.
Pan Javed Multani


1
SELECT id FROM `table` ORDER BY id DESC LIMIT 1

Chociaż wątpię w jego produktywność, ale jest w 100% niezawodny


Ja również zgadzam się, że jest to najprostsze podejście. Nie jestem pewien, dlaczego zostałeś przegłosowany, ale zrównoważę głosem za.
powtórzona

Nie wspomniałem o konieczności transakcji, jeśli nie zapakujesz jej w transakcję, ten kod jest kiepski, jak tylko spełnia rzeczywiste ładowanie.
Tebe

1
Co jeśli ostatni wiersz został usunięty? Czy wiele ostatnich wierszy zostało usuniętych?
Liam W

Zwolnione klucze nie są używane, chyba że wyraźnie to określisz
Tebe

1

używając odpowiedzi ravi404:

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

używając w zapytaniu wstawiającym, aby utworzyć skrót SHA1. dawny.:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( getAutoincrementalNextval ('document') ),
    'Title',
    'Body'
);

Czy to zawsze działa? Czy są warunki wyścigu, jeśli w tym samym czasie zdarzają się dwie wkładki?
Jmons

0

Poprawa @ ravi404, w przypadku gdy przesunięcie autoincrement NIE JEST 1:

SELECT (`auto_increment`-1) + IFNULL(@@auto_increment_offset,1) 
FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = your_table_name
AND table_schema = DATABASE( );

( auto_increment-1): silnik db wydaje się zawsze uwzględniać przesunięcie o 1. Więc musisz porzucić to założenie, a następnie dodać opcjonalną wartość @@ auto_increment_offset lub domyślnie 1: IFNULL (@@ auto_increment_offset, 1)


0

U mnie działa i wygląda prosto:

 $auto_inc_db = mysql_query("SELECT * FROM my_table_name  ORDER BY  id  ASC ");
 while($auto_inc_result = mysql_fetch_array($auto_inc_db))
 {
 $last_id = $auto_inc_result['id'];
 }
 $next_id = ($last_id+1);


 echo $next_id;//this is the new id, if auto increment is on

Dość niepotrzebne jest $last_idpowtarzalne przypisywanie, kiedy możesz po prostu DESC. Twój whileblok wykonał mnóstwo bezużytecznej pracy.
Tiw

tak, tak ... właśnie zdałem sobie sprawę, że to nie jest idealne ... :( koniec można powtórzyć identyfikator, jeśli został usunięty wcześniej ... :(
Toncsiking

0

Jeśli nie zwrócisz poprawnego AUTO_INCREMENT, spróbuj:

ANALYZE TABLE `my_table`;
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE (TABLE_NAME = 'my_table');

Ta czysta pamięć podręczna dla tabeli w BD

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.