Como obtenho o ID da última linha atualizada no MySQL usando PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Como obtenho o ID da última linha atualizada no MySQL usando PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Respostas:
Encontrei uma resposta para este problema :)
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 por aefxx
Essa técnica pode ser expandida ainda mais para recuperar o ID de cada linha afetada por uma instrução de atualização:
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
Isso retornará uma sequência com todos os IDs concatenados por vírgula.
WHERE
cláusula, você pode simplesmente usar a mesma WHERE
cláusula na sua próxima consulta.SELECT id FROM footable WHERE fooid > 5
LAST_INSERT_ID()
pode aceitar um argumento que definirá o valor retornado pela próxima chamada para LAST_INSERT_ID()
. Por exemplo: UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';
. Agora, SELECT LAST_INSERT_ID();
retornará o ID atualizado. Veja a resposta de newtover para mais detalhes.
UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);
. No entanto, ele não recupera vários IDs, portanto, essa resposta é superior.
Estou surpreso que, dentre as respostas, não vejo a solução mais fácil.
Suponha que item_id
seja uma coluna de identidade inteira na items
tabela e você atualize as linhas com a seguinte instrução:
UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';
Para conhecer a última linha afetada logo após a instrução, atualize-a levemente para o seguinte:
UPDATE items
SET qwe = 'qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();
Se você precisar atualizar apenas uma linha realmente alterada, será necessário adicionar uma atualização condicional do item_id por meio da verificação de LAST_INSERT_ID se os dados serão alterados na linha.
UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
Isso é oficialmente simples, mas notavelmente contra-intuitivo. Se você estiver fazendo:
update users set status = 'processing' where status = 'pending'
limit 1
Altere para este:
update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id)
limit 1
A adição de last_insert_id(user_id)
na where
cláusula está dizendo ao MySQL para definir sua variável interna para o ID da linha encontrada. Quando você passa um valor para last_insert_id(expr)
esse valor , ele retorna esse valor, que no caso de IDs como esse sempre é um número inteiro positivo e, portanto, sempre é avaliado como verdadeiro, nunca interferindo na cláusula where. Isso funciona apenas se alguma linha foi realmente encontrada; lembre-se de verificar as linhas afetadas. Você pode obter o ID de várias maneiras.
Você pode gerar sequências sem chamar LAST_INSERT_ID (), mas o utilitário de usar a função dessa maneira é que o valor do ID seja mantido no servidor como o último valor gerado automaticamente. É seguro para vários usuários porque vários clientes podem emitir a instrução UPDATE e obter seu próprio valor de sequência com a instrução SELECT (ou mysql_insert_id ()), sem afetar ou ser afetado por outros clientes que geram seus próprios valores de sequência.
Retorna o valor gerado para uma coluna AUTO_INCREMENT pela instrução INSERT ou UPDATE anterior. Use esta função depois de executar uma instrução INSERT em uma tabela que contém um campo AUTO_INCREMENT ou usar INSERT ou UPDATE para definir um valor de coluna com LAST_INSERT_ID (expr).
O motivo das diferenças entre LAST_INSERT_ID () e mysql_insert_id () é que LAST_INSERT_ID () é fácil de usar em scripts, enquanto mysql_insert_id () tenta fornecer informações mais precisas sobre o que acontece com a coluna AUTO_INCREMENT.
A execução de uma instrução INSERT ou UPDATE usando a função LAST_INSERT_ID () também modificará o valor retornado pela função mysqli_insert_id ().
Juntando tudo:
$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();
}
(FYI que classe DB está aqui .)
Esse é o mesmo método da resposta de Salman A, mas aqui está o código que você realmente precisa fazer.
Primeiro, edite sua tabela para que ela acompanhe automaticamente sempre que uma linha for modificada. Remova a última linha se você quiser saber apenas quando uma linha foi inserida inicialmente.
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
Em seguida, para descobrir a última linha atualizada, você pode usar esse código.
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
Todo esse código foi retirado do MySQL vs PostgreSQL: Adicionando uma coluna 'Last Modified Time' a uma tabela e Manual do MySQL: Classificando Linhas . Acabei de montar.
Inquerir :
$sqlQuery = "UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
Função PHP:
function updateAndGetId($sqlQuery)
{
mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
return mysql_insert_id();
}
É trabalho para mim;)
Mais ainda para a resposta acima aceita
Para aqueles que estavam se perguntando sobre :=
&=
Diferença significativa entre :=
e =
, e é isso que :=
funciona como um operador de atribuição de variável em qualquer lugar, enquanto =
só funciona dessa maneira nas instruções SET e é um operador de comparação em qualquer outro lugar.
Portanto SELECT @var = 1 + 1;
, @var
permanecerá inalterado e retornará um booleano (1 ou 0, dependendo do valor atual de @var), enquanto SELECT @var := 1 + 1;
mudará @var
para 2 e retornará 2 .
[Fonte]
Ei, eu só precisava de um truque - resolvi de uma maneira diferente, talvez funcione para você. Observe que essa não é uma solução escalável e será muito ruim para grandes conjuntos de dados.
Divida sua consulta em duas partes -
primeiro, selecione os IDs das linhas que você deseja atualizar e armazene-os em uma tabela temporária.
em segundo lugar, faça a atualização original com a condição na instrução de atualização alterada para where id in temp_table
.
E para garantir a simultaneidade, você precisa bloquear a tabela antes dessas duas etapas e soltar a trava no final.
Novamente, isso funciona para mim, para uma consulta que termina com limit 1
, então nem uso uma tabela temporária, mas simplesmente uma variável para armazenar o resultado da primeira select
.
Prefiro esse método, pois sei que sempre atualizarei apenas uma linha e o código é direto.
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;
Eu tive que CAST o id (não sei por que) ... ou não consigo obter o conteúdo @uids (era um blob) Btw muito obrigado pela resposta Pomyk!
O ID da última linha atualizada é o mesmo que você usa no 'updateQuery' para encontrar e atualizar essa linha. Portanto, salve (ligue) esse ID da maneira que desejar.
last_insert_id()
depende do AUTO_INCREMENT
, mas o último ID atualizado não.
Minha solução é, primeiro decida o "id" (@uids) com o comando select e depois atualize esse id com @uids.
SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;
funcionou no meu projeto.
Se você está apenas inserindo e deseja uma da mesma sessão, faça conforme a resposta da peirix. Se você estiver fazendo modificações, precisará modificar o esquema do banco de dados para armazenar qual entrada foi atualizada mais recentemente.
Se você deseja o ID da última modificação, que pode ter sido de uma sessão diferente (por exemplo, não aquela que foi feita apenas pelo código PHP em execução no momento, mas que foi feita em resposta a uma solicitação diferente), você pode adicionar um TIMESTAMP na sua tabela chamada last_modified (consulte http://dev.mysql.com/doc/refman/5.1/en/datetime.html para obter informações) e, quando você atualizar, defina last_modified = CURRENT_TIME.
Depois de definir isso, você poderá usar uma consulta como: SELECT id FROM tabela ORDER BY last_modified DESC LIMIT 1; para obter a linha modificada mais recentemente.