LAST_INSERT_ID () MySQL

151

Mam pytanie dotyczące MySQL, które wydaje mi się dość łatwe. Muszę zwrócić OSTATNI WSTAWIONY ID z tabeli1, gdy uruchamiam następujące zapytanie MySql:

INSERT INTO table1 (title,userid) VALUES ('test',1); 
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(),4,1);
SELECT LAST_INSERT_ID();

Jak rozumiesz, bieżący kod zwróci po prostu LAST INSERT ID tabeli2 zamiast tabeli1, jak mogę uzyskać identyfikator z tabeli1, nawet jeśli wstawię do tabeli2 między?

Jaskółka oknówka
źródło

Odpowiedzi:

248

Możesz przechowywać ostatni identyfikator wstawiania w zmiennej:

INSERT INTO table1 (title,userid) VALUES ('test', 1); 
SET @last_id_in_table1 = LAST_INSERT_ID();
INSERT INTO table2 (parentid,otherid,userid) VALUES (@last_id_in_table1, 4, 1);    

Lub pobierz max id frm table1

INSERT INTO table1 (title,userid) VALUES ('test', 1); 
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(), 4, 1); 
SELECT MAX(id) FROM table1;   
Julien Hoarau
źródło
5
Dzięki! Nie udało mi się to najpierw działać, ponieważ korzystałem z asp.net z MySQL i musiałem dodać Zezwalaj na zmienne użytkownika = True do parametrów połączenia, aby zezwolić na zmienne.
Martin
114
max nie jest dobrym pomysłem, ponieważ możesz przegrać wyścig z innym wprowadzającym.
Rob Starling,
5
@RobStarling Całkowicie się zgadzam, ale na wypadek, gdyby ktoś absolutnie tego potrzebował; użyj transakcji z odpowiednim poziomem izolacji.
Aidiakapi
8
co jeśli 2 INSERTY wydarzy się w tym samym czasie lub jedna przed drugą?
FosAvance,
32
@FosAvance LAST_INSERT_ID () jest specyficzne połączenie ref
Momin Al Aziz
18

Ponieważ faktycznie zapisałeś poprzednią LAST_INSERT_ID () w drugiej tabeli, możesz ją stamtąd pobrać:

INSERT INTO table1 (title,userid) VALUES ('test',1); 
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(),4,1);
SELECT parentid FROM table2 WHERE id = LAST_INSERT_ID();
Artem Goutsoul
źródło
13

Umożliwia to wstawienie wiersza do 2 różnych tabel i utworzenie odniesienia do obu tabel.

START TRANSACTION;
INSERT INTO accounttable(account_username) 
    VALUES('AnAccountName');
INSERT INTO profiletable(profile_account_id) 
    VALUES ((SELECT account_id FROM accounttable WHERE account_username='AnAccountName'));
    SET @profile_id = LAST_INSERT_ID(); 
UPDATE accounttable SET `account_profile_id` = @profile_id;
COMMIT;
Ospho
źródło
1
Dobry strzał na transakcji.
Kurt Van den Branden
1
Ale: dostępne tylko w InnoDB.
raiserle
4

Miałem ten sam problem w bashu i robię coś takiego:

mysql -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');"

co działa dobrze :-) Ale

mysql -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');set @last_insert_id = LAST_INSERT_ID();"
mysql -D "dbname" -e "insert into table2 (id_tab1) values (@last_insert_id);"

nie działa. Ponieważ po pierwszym poleceniu powłoka zostanie wylogowana z mysql i zalogowana ponownie dla drugiego polecenia, a następnie zmienna @last_insert_id nie jest już ustawiona. Moje rozwiązanie to:

lastinsertid=$(mysql -B -N -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');select LAST_INSERT_ID();")
mysql -D "dbname" -e "insert into table2 (id_tab1) values (${lastinsertid});"

Może ktoś szuka rozwiązania i bash :-)

Eugen Spinne
źródło
LAST_INSERT_IDdostępne tylko dla aktywnego połączenia. #mysq-command connect dla każdego polecenia. Możesz połączyć się z mysqlpoleceniem z serwerem i wstawić swoje zapytania lub możesz utworzyć plik tekstowy i mysqlpolecenie z przekierowaniem z pliku txt akamysql [connection option] < txt.file
raiserle
1

Mamy tylko jedną osobę wprowadzającą rekordy, więc zaraz po wstawieniu wykonuję następujące zapytanie:

$result = $conn->query("SELECT * FROM corex ORDER BY id DESC LIMIT 1");

while ($row = $result->fetch_assoc()) {

            $id = $row['id'];

}

To pobiera ostatni identyfikator z bazy danych.

sspence65
źródło
1
Musiałem podać ważny przykład, więc użyłem tego, którego używam. Gdybym zrobił to w C, prawdopodobnie narzekałbyś „nie każdy używa C” ....
sspence65
Chyba najbezpieczniejszy i najprostszy ze wszystkich;)
Anjana Silva
1

W przypadku braku rozwiązania InnoDB: możesz skorzystać z procedury don't forgot to set the the delimiter for storing the procedure with ;

CREATE PROCEDURE myproc(OUT id INT, IN otherid INT, IN title VARCHAR(255))
BEGIN
LOCK TABLES `table1` WRITE;
INSERT INTO `table1` ( `title` ) VALUES ( @title ); 
SET @id = LAST_INSERT_ID();
UNLOCK TABLES;
INSERT INTO `table2` ( `parentid`, `otherid`, `userid` ) VALUES (@id, @otherid, 1); 
END

I możesz go użyć ...

SET @myid;
CALL myproc( @myid, 1, "my title" );
SELECT @myid;
raiserle
źródło
0

Czy byłoby możliwe zapisanie zmiennej last_id_in_table1 w zmiennej php, aby użyć jej później?

Z tym last_id muszę dołączyć niektóre rekordy w innej tabeli z tym last_id, więc potrzebuję:

1) Wykonaj INSERT i pobierz last_id_in_table1

INSERT into Table1(name) values ("AAA"); 
SET @last_id_in_table1 = LAST_INSERT_ID();

2) W przypadku jakichkolwiek nieokreślonych wierszy w innej tabeli, ZAKTUALIZOWANIE tych wierszy za pomocą parametru last_id_insert wygenerowanego we wstawianiu.

$element = array(some ids)    
foreach ($element as $e){ 
         UPDATE Table2 SET column1 = @last_id_in_table1 WHERE id = $e 
    }
Anioł
źródło
0

Zamiast tego LAST_INSERT_ID() spróbuj użyć tego

mysqli_insert_id(connection)
Sambit Kumar Dalai
źródło
-1

Przedostatni i przedostatni:

INSERT INTO `t_parent_user`(`u_id`, `p_id`) VALUES ((SELECT MAX(u_id-1) FROM user) ,(SELECT MAX(u_id) FROM user  ) );
user2541471
źródło
To rozwiązanie nie jest bezpieczne poza transakcją (tj. Włączone autocommit) i wewnątrz transakcji z poziomem izolacji transakcji poniżej możliwego do serializacji. Zobacz: en.wikipedia.org/wiki/Isolation_(database_systems)
snorbi
-2

Aby dodać do postu Rodrigo, zamiast LAST_INSERT_ID () w zapytaniu możesz użyć SELECT MAX (id) FROM table1;, ale musisz użyć (),

INSERT INTO table1 (title,userid) VALUES ('test', 1)
INSERT INTO table2 (parentid,otherid,userid) VALUES ( (SELECT MAX(id) FROM table1), 4, 1)
Pavlen
źródło
To rozwiązanie nie jest bezpieczne poza transakcją (tj. Włączone autocommit) i wewnątrz transakcji z poziomem izolacji transakcji poniżej możliwego do serializacji. Zobacz: en.wikipedia.org/wiki/Isolation_(database_systems)
snorbi
-9

Jeśli chcesz mieć z mysql, po zapytaniu, ostatni auto-inkrementalny identyfikator bez kolejnego zapytania, wpisz swój kod:

mysql_insert_id();
Luca Perico
źródło
15
Nie polecaj mysql_ * - te są przestarzałe
German Rumm
cletus otrzymał 106 głosów za i oznaczył odpowiedź dla mysql_insert_id tutaj: stackoverflow.com/a/897361/153923
jp2code
2
cletus odpowiedział w 2009 roku! mysql jest przestarzały, lepiej używać mysqli i mysqli_insert_id ie2.php.net/mysqli_insert_id
Maciej Paprocki
2
Luca, jeśli usuniesz tę nieaktualną odpowiedź, wierzę, że Twoje punkty reputacji zostaną zwrócone.
TecBrat
Inną dobrą alternatywą dla przestarzałej sugestii jest PDO :: lastInsertId ( php.net/manual/en/pdo.lastinsertid.php )
w5m