mysqli_insert_id ($ link) retournera exactement l'id de la dernière ligne mise à jour. J'utilise cette fonction dans mes projets dans le même but. Vous pouvez l'utiliser à la fois dans des requêtes synchrones ou asynchrones. Insérez simplement $ lastupdated_row_id = mysqli_insert_id ($ link) dans votre code et cela fonctionnera pour vous.
Naeem Ul Wahhab
1
Vous ne connaissez pas déjà l'ID de la ligne si vous mettez à jour? Je suppose qu'il doit y avoir des cas où vous ne le faites pas.
JCharette
1
Vous utilisez probablement une clause where dans votre requête de mise à jour, pourquoi ne pouvez-vous pas utiliser la même clause where dans la requête de sélection? UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1?
Salman A
Réponses:
236
J'ai trouvé une réponse à ce problème :)
SET @update_id:=0;
UPDATE some_table SET column_name ='value', id =(SELECT @update_id:= id)
WHERE some_other_column ='blah' LIMIT 1;
SELECT @update_id;
EDIT par aefxx
Cette technique peut être encore développée pour récupérer l'ID de chaque ligne affectée par une instruction de mise à jour:
SET @uids:=null;
UPDATE footable
SET foo ='bar'
WHERE fooid >5
AND ( SELECT @uids:= CONCAT_WS(',', fooid,@uids));
SELECT @uids;
Cela renverra une chaîne avec tous les ID concaténés par une virgule.
Je ne peux pas croire que cela ait eu 0 vote positif, et le commentaire mysql_insert_id () qui n'est pas du tout ce que l'OP demandait en a 13. Merci Pomyk, une astuce intelligente!
Jaka Jančar du
1
Puisque vous avez une WHEREclause, vous pouvez simplement utiliser la même WHEREclause dans votre prochaine requêteSELECT id FROM footable WHERE fooid > 5
Salman A
4
Peut-être que tout le monde comprend cela, mais si vous utilisez mysql_query (); vous devez diviser cela en trois appels différents, mais cela fonctionnera.
rael_kid
8
Il n'est même pas nécessaire d'utiliser des variables. LAST_INSERT_ID()peut accepter un argument qui définira la valeur renvoyée par le prochain appel à LAST_INSERT_ID(). Par exemple: UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';. Maintenant, SELECT LAST_INSERT_ID();retournera l'ID mis à jour. Voir la réponse de newtover pour plus de détails.
Joel le
3
@SteveChilds Je viens de commenter la question de Newtover et je souhaite ajouter une solution à l'écueil que vous décrivez. Ce jeux LAST_INSERT_ID à 0 s'il n'y a rien à MISE À JOUR: UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);. Cependant, il ne récupère pas plusieurs identifiants, donc cette réponse est supérieure.
martinczerwi
33
Hm, je suis surpris que parmi les réponses je ne vois pas la solution la plus simple.
Supposons, item_idest une colonne d'identité entière dans la itemstable et que vous mettez à jour les lignes avec l'instruction suivante:
UPDATE items
SET qwe ='qwe'
WHERE asd ='asd';
Ensuite, pour connaître la dernière ligne affectée juste après l'instruction, vous devez légèrement mettre à jour l'instruction comme suit:
UPDATE items
SET qwe ='qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd ='asd';
SELECT LAST_INSERT_ID();
Si vous avez besoin de mettre à jour uniquement la ligne réellement modifiée, vous devez ajouter une mise à jour conditionnelle de l'item_id via le LAST_INSERT_ID vérifiant si les données vont changer dans la ligne.
Il est sécurisé pour plusieurs utilisateurs car plusieurs clients peuvent émettre l'instruction UPDATE et obtenir leur propre valeur de séquence avec l'instruction SELECT (ou mysql_insert_id ()), sans affecter ni être affectés par d'autres clients qui génèrent leurs propres valeurs de séquence. Selon dev.mysql.com/doc/refman/5.0/en/…
brutuscat
1
Cela ne va-t-il pas définir le item_id sur le dernier enregistrement inséré?
arleslie
2
@arleslie, si vous suivez le lien vers les documents dans le commentaire du brutuscat ci-dessus, vous verrez que ce n'est pas le cas. C'est exactement le comportement prévu pour le cas.
newtover
1
C'est en effet la bonne réponse. Bien que la requête semble un peu contre-intuitive, c'est exactement ce que la documentation MySQL dit de faire.
Timothy Zorn
3
Au cas où la requête vous confondrait, puisque LAST_INSERT_ID (expr) retournera la valeur de expr pour l'appel UPDATE, vous pouvez également l'utiliser comme ceci:UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
martinczerwi
14
C'est officiellement simple mais remarquablement contre-intuitif. Si vous faites:
update users set status ='processing'where status ='pending'
limit 1
Changez-le en ceci:
update users set status ='processing'where status ='pending'and last_insert_id(user_id)
limit 1
L'ajout de last_insert_id(user_id)dans la whereclause indique à MySQL de définir sa variable interne sur l'ID de la ligne trouvée. Lorsque vous passez une valeur à last_insert_id(expr)like this, cela finit par renvoyer cette valeur, qui dans le cas d'ID comme ici est toujours un entier positif et donc toujours évalué à true, n'interférant jamais avec la clause where. Cela ne fonctionne que si une ligne a été trouvée, alors n'oubliez pas de vérifier les lignes affectées. Vous pouvez ensuite obtenir l'ID de plusieurs manières.
Vous pouvez générer des séquences sans appeler LAST_INSERT_ID (), mais l'utilité d'utiliser la fonction de cette façon est que la valeur d'ID est conservée dans le serveur comme la dernière valeur générée automatiquement. Il est sécurisé pour plusieurs utilisateurs car plusieurs clients peuvent émettre l'instruction UPDATE et obtenir leur propre valeur de séquence avec l'instruction SELECT (ou mysql_insert_id ()), sans affecter ni être affectés par d'autres clients qui génèrent leurs propres valeurs de séquence.
Renvoie la valeur générée pour une colonne AUTO_INCREMENT par l'instruction INSERT ou UPDATE précédente. Utilisez cette fonction après avoir exécuté une instruction INSERT dans une table qui contient un champ AUTO_INCREMENT, ou après avoir utilisé INSERT ou UPDATE pour définir une valeur de colonne avec LAST_INSERT_ID (expr).
La raison des différences entre LAST_INSERT_ID () et mysql_insert_id () est que LAST_INSERT_ID () est facile à utiliser dans les scripts tandis que mysql_insert_id () essaie de fournir des informations plus exactes sur ce qui arrive à la colonne AUTO_INCREMENT.
L'exécution d'une instruction INSERT ou UPDATE à l'aide de la fonction LAST_INSERT_ID () modifiera également la valeur renvoyée par la fonction mysqli_insert_id ().
Mettre tous ensemble:
$affected_rows = DB::getAffectedRows("
update users set status = 'processing'
where status = 'pending' and last_insert_id(user_id)
limit 1");if($affected_rows){
$user_id = DB::getInsertId();}
Important à noter: ceci est sécurisé pour plusieurs connexions, la valeur persistante pour last_insert_id ou mysql_insert_id (et peut-être mysqli_insert_id, je n'ai pas vérifié), est par connexion. Impressionnant!
Ryan S
11
C'est la même méthode que la réponse de Salman A, mais voici le code dont vous avez réellement besoin pour le faire.
Tout d'abord, modifiez votre tableau afin qu'il garde automatiquement une trace de chaque fois qu'une ligne est modifiée. Supprimez la dernière ligne si vous souhaitez uniquement savoir quand une ligne a été initialement insérée.
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
Ensuite, pour connaître la dernière ligne mise à jour, vous pouvez utiliser ce code.
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
Cette méthode peut récupérer le mauvais identifiant si la deuxième insertion est effectuée juste après la première requête d'insertion. Cependant, si nous utilisons 'WHERE' avec cette requête, c'est-à-dire SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1 WHERE (certaines conditions liées à la dernière requête d'insertion), cela peut empêcher de récupérer le mauvais ID.
Naeem Ul Wahhab
1
@ TheNoble-Coder C'est vrai. Si vous avez besoin d'obtenir l'ID d'une ligne affectée d'une requête de mise à jour particulière, utilisez la technique de Pomyk. Cette technique est ici plus utile lorsqu'elle est utilisée de manière asynchrone, où vous voulez juste la dernière mise à jour absolue.
Chad von Nau
5
Requete :
$sqlQuery ="UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
Fonction PHP:
function updateAndGetId($sqlQuery){
mysql_query(str_replace("SET","SET id = LAST_INSERT_ID(id),", $sqlQuery));return mysql_insert_id();}
De plus la réponse ci - dessus Accepted Pour ceux qui se demandaient sur les :=&=
Différence significative entre :=et =, et cela :=fonctionne comme un opérateur d'affectation de variable partout, alors qu'il =ne fonctionne que de cette façon dans les instructions SET, et est un opérateur de comparaison partout ailleurs.
Donc SELECT @var = 1 + 1;laissera @varinchangé et retournera un booléen (1 ou 0 selon la valeur actuelle de @var), tandis que SELECT @var := 1 + 1;changera @varen 2 et retournera 2 .
[La source]
Hey, merci. Ce qu'ils signifient est en fait plus intéressant que la réponse acceptée ci-dessus.
Vert du
2
Hé, j'avais juste besoin d'un tel truc - je l'ai résolu d'une manière différente, peut-être que ça marchera pour toi. Notez que ce n'est pas une solution évolutive et que ce sera très mauvais pour les grands ensembles de données.
Divisez votre requête en deux parties -
Sélectionnez d'abord les identifiants des lignes que vous souhaitez mettre à jour et stockez-les dans une table temporaire.
deuxièmement, effectuez la mise à jour d'origine avec la condition de l'instruction de mise à jour modifiée en where id in temp_table.
Et pour assurer la concurrence, vous devez verrouiller la table avant ces deux étapes, puis relâcher le verrou à la fin.
Encore une fois, cela fonctionne pour moi, pour une requête qui se termine par limit 1, donc je n'utilise même pas de table temporaire, mais simplement une variable pour stocker le résultat de la première select.
Je préfère cette méthode car je sais que je ne mettrai toujours à jour qu'une seule ligne et que le code est simple.
SET @uids:="";
UPDATE myf___ingtable
SET id = id
WHERE id <5
AND ( SELECT @uids:= CONCAT_WS(',', CAST(id AS CHAR CHARACTER SET utf8),@uids));
SELECT @uids;
J'ai dû CAST l'ID (je ne sais pas pourquoi) ... ou je ne peux pas obtenir le contenu @uids (c'était un blob) Btw merci beaucoup pour la réponse de Pomyk!
L'ID de la dernière ligne mise à jour est le même que celui que vous utilisez dans la 'updateQuery' pour trouver et mettre à jour cette ligne. Donc, enregistrez simplement (appelez) cet identifiant comme vous le souhaitez.
last_insert_id()dépend de AUTO_INCREMENT, mais pas le dernier ID mis à jour.
Si vous ne faites que des insertions et que vous en voulez une de la même session, faites selon la réponse de peirix. Si vous effectuez des modifications, vous devrez modifier le schéma de votre base de données pour stocker l'entrée qui a été la plus récemment mise à jour.
Si vous voulez l'id de la dernière modification, qui peut provenir d'une session différente (c'est-à-dire pas celle qui vient d'être faite par le code PHP en cours d'exécution actuellement, mais celle qui a été faite en réponse à une requête différente), vous pouvez ajouter un TIMESTAMP à votre table appelée last_modified (voir http://dev.mysql.com/doc/refman/5.1/en/datetime.html pour plus d'informations), puis lorsque vous mettez à jour, définissez last_modified = CURRENT_TIME.
Après avoir défini ceci, vous pouvez alors utiliser une requête comme: SELECT id FROM table ORDER BY last_modified DESC LIMIT 1; pour obtenir la ligne la plus récemment modifiée.
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?Réponses:
J'ai trouvé une réponse à ce problème :)
EDIT par aefxx
Cette technique peut être encore développée pour récupérer l'ID de chaque ligne affectée par une instruction de mise à jour:
Cela renverra une chaîne avec tous les ID concaténés par une virgule.
la source
WHERE
clause, vous pouvez simplement utiliser la mêmeWHERE
clause dans votre prochaine requêteSELECT id FROM footable WHERE fooid > 5
LAST_INSERT_ID()
peut accepter un argument qui définira la valeur renvoyée par le prochain appel àLAST_INSERT_ID()
. Par exemple:UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';
. Maintenant,SELECT LAST_INSERT_ID();
retournera l'ID mis à jour. Voir la réponse de newtover pour plus de détails.UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);
. Cependant, il ne récupère pas plusieurs identifiants, donc cette réponse est supérieure.Hm, je suis surpris que parmi les réponses je ne vois pas la solution la plus simple.
Supposons,
item_id
est une colonne d'identité entière dans laitems
table et que vous mettez à jour les lignes avec l'instruction suivante:Ensuite, pour connaître la dernière ligne affectée juste après l'instruction, vous devez légèrement mettre à jour l'instruction comme suit:
Si vous avez besoin de mettre à jour uniquement la ligne réellement modifiée, vous devez ajouter une mise à jour conditionnelle de l'item_id via le LAST_INSERT_ID vérifiant si les données vont changer dans la ligne.
la source
UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
C'est officiellement simple mais remarquablement contre-intuitif. Si vous faites:
Changez-le en ceci:
L'ajout de
last_insert_id(user_id)
dans lawhere
clause indique à MySQL de définir sa variable interne sur l'ID de la ligne trouvée. Lorsque vous passez une valeur àlast_insert_id(expr)
like this, cela finit par renvoyer cette valeur, qui dans le cas d'ID comme ici est toujours un entier positif et donc toujours évalué à true, n'interférant jamais avec la clause where. Cela ne fonctionne que si une ligne a été trouvée, alors n'oubliez pas de vérifier les lignes affectées. Vous pouvez ensuite obtenir l'ID de plusieurs manières.MySQL
last_insert_id()
MySQL
mysql_insert_id()
PHP
mysqli_insert_id()
Mettre tous ensemble:
(Pour info, cette classe DB est ici .)
la source
C'est la même méthode que la réponse de Salman A, mais voici le code dont vous avez réellement besoin pour le faire.
Tout d'abord, modifiez votre tableau afin qu'il garde automatiquement une trace de chaque fois qu'une ligne est modifiée. Supprimez la dernière ligne si vous souhaitez uniquement savoir quand une ligne a été initialement insérée.
Ensuite, pour connaître la dernière ligne mise à jour, vous pouvez utiliser ce code.
Ce code est tout extrait de MySQL vs PostgreSQL: Ajout d'une colonne 'Last Modified Time' à une table et MySQL Manual: Sorting Rows . Je viens de l'assembler.
la source
Requete :
Fonction PHP:
C'est du travail pour moi;)
la source
De plus la réponse ci - dessus Accepted
Pour ceux qui se demandaient sur les
:=
&=
Différence significative entre
:=
et=
, et cela:=
fonctionne comme un opérateur d'affectation de variable partout, alors qu'il=
ne fonctionne que de cette façon dans les instructions SET, et est un opérateur de comparaison partout ailleurs.Donc
SELECT @var = 1 + 1;
laissera@var
inchangé et retournera un booléen (1 ou 0 selon la valeur actuelle de @var), tandis queSELECT @var := 1 + 1;
changera@var
en 2 et retournera 2 . [La source]la source
Hé, j'avais juste besoin d'un tel truc - je l'ai résolu d'une manière différente, peut-être que ça marchera pour toi. Notez que ce n'est pas une solution évolutive et que ce sera très mauvais pour les grands ensembles de données.
Divisez votre requête en deux parties -
Sélectionnez d'abord les identifiants des lignes que vous souhaitez mettre à jour et stockez-les dans une table temporaire.
deuxièmement, effectuez la mise à jour d'origine avec la condition de l'instruction de mise à jour modifiée en
where id in temp_table
.Et pour assurer la concurrence, vous devez verrouiller la table avant ces deux étapes, puis relâcher le verrou à la fin.
Encore une fois, cela fonctionne pour moi, pour une requête qui se termine par
limit 1
, donc je n'utilise même pas de table temporaire, mais simplement une variable pour stocker le résultat de la premièreselect
.Je préfère cette méthode car je sais que je ne mettrai toujours à jour qu'une seule ligne et que le code est simple.
la source
J'ai dû CAST l'ID (je ne sais pas pourquoi) ... ou je ne peux pas obtenir le contenu @uids (c'était un blob) Btw merci beaucoup pour la réponse de Pomyk!
la source
L'ID de la dernière ligne mise à jour est le même que celui que vous utilisez dans la 'updateQuery' pour trouver et mettre à jour cette ligne. Donc, enregistrez simplement (appelez) cet identifiant comme vous le souhaitez.
last_insert_id()
dépend deAUTO_INCREMENT
, mais pas le dernier ID mis à jour.la source
Ma solution est de décider d'abord de l '"id" (@uids) avec la commande select et après la mise à jour de cet identifiant avec @uids.
cela a fonctionné sur mon projet.
la source
Si vous ne faites que des insertions et que vous en voulez une de la même session, faites selon la réponse de peirix. Si vous effectuez des modifications, vous devrez modifier le schéma de votre base de données pour stocker l'entrée qui a été la plus récemment mise à jour.
Si vous voulez l'id de la dernière modification, qui peut provenir d'une session différente (c'est-à-dire pas celle qui vient d'être faite par le code PHP en cours d'exécution actuellement, mais celle qui a été faite en réponse à une requête différente), vous pouvez ajouter un TIMESTAMP à votre table appelée last_modified (voir http://dev.mysql.com/doc/refman/5.1/en/datetime.html pour plus d'informations), puis lorsque vous mettez à jour, définissez last_modified = CURRENT_TIME.
Après avoir défini ceci, vous pouvez alors utiliser une requête comme: SELECT id FROM table ORDER BY last_modified DESC LIMIT 1; pour obtenir la ligne la plus récemment modifiée.
la source
Pas besoin de code Mysql aussi long. En PHP, la requête doit ressembler à ceci:
la source