MySQL에서 마지막으로 업데이트 된 행의 ID를 얻는 방법은 무엇입니까?


134

PHP를 사용하여 MySQL에서 마지막으로 업데이트 된 행의 ID를 어떻게 얻습니까?


2
mysqli_insert_id ($ link)는 마지막으로 업데이트 된 행의 ID를 정확하게 반환합니다. 나는 같은 목적으로 프로젝트 에서이 기능을 사용하고 있습니다. 동기식 또는 비동기식 쿼리 모두에서 사용할 수 있습니다. 코드에 $ lastupdated_row_id = mysqli_insert_id ($ link)를 삽입하면 효과가 있습니다.
Naeem Ul Wahhab

1
업데이트하면 이미 행의 ID를 모르십니까? 당신이하지 않는 경우가있을 것 같아요.
JCharette

1
아마도 업데이트 쿼리에 where 절을 사용할 것입니다. 왜 select 쿼리에 동일한 where 절을 사용할 수 없습니까? UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1?
살만 A

답변:


236

이 문제에 대한 답을 찾았습니다 :)

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;

aefxx로 편집

이 기술은 update 문에 영향을받는 모든 행의 ID를 검색하도록 추가로 확장 될 수 있습니다.

SET @uids := null;
UPDATE footable
   SET foo = 'bar'
 WHERE fooid > 5
   AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;

쉼표로 연결된 모든 ID가 포함 된 문자열을 반환합니다.


6
이것은 0 upvotes를 가지고 있다고 생각할 수 없으며 OP가 전혀 요구하지 않은 mysql_insert_id () 주석에는 13이 있습니다. 감사합니다. Pomyk, 영리한 트릭입니다!
Jaka Jančar

1
당신이 가지고 있기 때문에 WHERE절을 당신은 단순히 동일한 사용할 수 있습니다 WHERE다음 쿼리 절을SELECT id FROM footable WHERE fooid > 5
살만

4
어쩌면 모든 사람이 이것을 이해할 수 있지만 mysql_query (); 이것을 세 가지 다른 호출로 나누어야하지만 작동합니다.
rael_kid

8
변수를 사용할 필요조차 없습니다. LAST_INSERT_ID()에 대한 다음 호출에서 반환 된 값을 설정하는 인수를 사용할 수 있습니다 LAST_INSERT_ID(). 예를 들면 다음과 같습니다 UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';.. 이제 SELECT LAST_INSERT_ID();업데이트 된 ID를 반환합니다. 자세한 내용은 newtover의 답변을 참조하십시오.
Joel

3
@SteveChilds 방금 newtover의 질문에 대해 언급하고 있었고 설명하는 함정에 해결책을 추가하고 싶습니다. UPDATE :에 아무것도 없으면 LAST_INSERT_ID를 0으로 설정합니다 UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);. 그러나 여러 ID를 검색하지 않으므로이 대답이 우수합니다.
martinczerwi

33

흠, 나는 대답 중 가장 쉬운 해결책을 찾지 못한다는 것에 놀랐다.

테이블 item_id의 정수 ID 열 items이고 다음 명령문으로 행을 갱신 한다고 가정하십시오 .

UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';

그런 다음 명령문 바로 다음에 영향을받는 최신 행을 알려면 명령문을 다음과 같이 약간 업데이트해야합니다.

UPDATE items
SET qwe = 'qwe',
    item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();

실제로 변경된 행만 업데이트해야하는 경우 LAST_INSERT_ID를 통해 item_id의 조건부 업데이트를 추가하여 행에서 데이터가 변경되는지 확인해야합니다.


3
여러 클라이언트가 자신의 시퀀스 값을 생성하는 다른 클라이언트의 영향을 받거나 영향을받지 않고 UPDATE 문을 실행하고 SELECT 문 (또는 mysql_insert_id ())을 사용하여 자체 시퀀스 값을 얻을 수 있기 때문에 다중 사용자 안전합니다. 당으로 dev.mysql.com/doc/refman/5.0/en/...
brutuscat

1
이것은 item_id를 마지막으로 삽입 된 레코드로 설정하지 않습니까?
arleslie

2
@arleslie, 위의 brutuscat의 의견에있는 문서 링크를 따라 가면 그렇지 않습니다. 이것은 사건에 대한 의도 된 행동입니다.
newtover

1
이것은 실제로 정답입니다. 쿼리는 약간 반 직관적 인 것처럼 보이지만 이것이 바로 MySQL 설명서의 지시에 따릅니다.
Timothy Zorn

3
쿼리가 혼란 스러울 경우 LAST_INSERT_ID (expr)가 UPDATE 호출에 대한 expr 값을 반환하므로 다음과 같이 사용할 수도 있습니다.UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
martinczerwi

14

이것은 공식적으로 간단하지만 현저하게 반 직관적입니다. 당신이하고있는 경우 :

update users set status = 'processing' where status = 'pending'
limit 1

이것을 다음과 같이 변경하십시오.

update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id) 
limit 1

last_insert_id(user_id)where절을 추가 하면 MySQL에게 내부 변수를 찾은 행의 ID 로 설정 하도록 지시합니다. 이와 last_insert_id(expr)같은 값을 전달하면 해당 값 이 반환됩니다. 여기에서 ID와 같은 경우 항상 양의 정수이므로 where 절을 방해하지 않고 항상 true로 평가됩니다. 이것은 실제로 일부 행이 발견 된 경우에만 작동하므로 영향을받는 행을 확인해야합니다. 그런 다음 여러 가지 방법으로 ID를 얻을 수 있습니다.

MySQL last_insert_id()

LAST_INSERT_ID ()를 호출하지 않고 시퀀스를 생성 할 수 있지만이 방법으로 함수를 사용하면 서버에서 ID 값이 마지막으로 자동 생성 된 값으로 유지됩니다. 여러 클라이언트가 자신의 시퀀스 값을 생성하는 다른 클라이언트의 영향을 받거나 영향을받지 않고 UPDATE 문을 실행하고 SELECT 문 (또는 mysql_insert_id ())을 사용하여 자체 시퀀스 값을 얻을 수 있기 때문에 다중 사용자 안전합니다.

MySQL mysql_insert_id()

이전 INSERT 또는 UPDATE 문으로 AUTO_INCREMENT 열에 대해 생성 된 값을 반환합니다. AUTO_INCREMENT 필드를 포함하는 테이블에 INSERT 문을 수행하거나 INSERT 또는 UPDATE를 사용하여 LAST_INSERT_ID (expr)로 컬럼 값을 설정 한 후에이 함수를 사용하십시오.

LAST_INSERT_ID ()와 mysql_insert_id ()의 차이점은 스크립트에서 LAST_INSERT_ID ()를 쉽게 사용할 수 있고 mysql_insert_id ()가 AUTO_INCREMENT 열에 발생하는 상황에 대한보다 정확한 정보를 제공하려고하기 때문입니다.

PHP mysqli_insert_id()

LAST_INSERT_ID () 함수를 사용하여 INSERT 또는 UPDATE 문을 수행하면 mysqli_insert_id () 함수가 반환 한 값도 수정됩니다.

함께 모아서:

$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();
}

(참고로 DB 클래스는 여기에 있습니다 .)


참고 사항 : 이것은 다중 연결 안전이며 last_insert_id 또는 mysql_insert_id (및 mysqli_insert_id, 확인하지 않은)의 지속 값은 연결 당입니다. 대박!
Ryan S

11

이것은 Salman A의 답변과 동일한 방법이지만 실제로 수행 해야하는 코드는 다음과 같습니다.

먼저 행이 수정 될 때마다 자동으로 추적되도록 테이블을 편집하십시오. 행이 처음 삽입 된시기 만 알고 싶다면 마지막 행을 제거하십시오.

ALTER TABLE mytable
ADD lastmodified TIMESTAMP 
    DEFAULT CURRENT_TIMESTAMP 
    ON UPDATE CURRENT_TIMESTAMP;

그런 다음 마지막으로 업데이트 된 행을 찾으려면이 코드를 사용할 수 있습니다.

SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;

이 코드는 MySQL과 PostgreSQL : 테이블에 '최근 수정 시간'열 추가MySQL 매뉴얼 : 정렬 행 에서 모두 해제되었습니다 . 방금 조립했습니다.


7
첫 번째 삽입 쿼리 직후에 두 번째 삽입이 수행되면이 메소드가 잘못된 ID를 페치 할 수 있습니다. 그러나이 쿼리에 'WHERE'를 사용하면 (예 : SELECTtable FROM mytable ORDER BY lastmodified DESC LIMIT 1 WHERE (마지막 삽입 쿼리 관련 조건)) 잘못된 ID를 가져 오지 못할 수 있습니다.
Naeem Ul Wahhab

1
@ TheNoble-Coder 이것은 사실입니다. 특정 업데이트 쿼리에 영향을 미치는 행 ID를 가져와야하는 경우 Pomyk의 기술을 사용하십시오. 이 기술은 비동기식으로 사용될 때 더 유용합니다. 여기서 절대 마지막 업데이트 만 원합니다.
차드 폰 나우

5

검색어 :

$sqlQuery = "UPDATE 
            update_table 
        SET 
            set_name = 'value' 
        WHERE 
            where_name = 'name'
        LIMIT 1;";

PHP 기능 :

function updateAndGetId($sqlQuery)
{
    mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
    return mysql_insert_id();
}

그것은 나를 위해 일한다.)


나는 똑같이 좋아하지만

3

위의 허용 응답에 더욱 더
궁금했다 분들을 위해 :=&=

유의 한 차이 사이 :==, 그것은 즉 :=동안, 모든 곳에서 가변 할당 연산자와 같은 작품 =에만 SET 문에서 그런 식으로 작동하고, 다른 곳 비교 연산자입니다.

따라서 변경되지 않은 SELECT @var = 1 + 1;상태로두고 부울 (@var의 현재 값에 따라 1 또는 0) 을 반환 하고 2로 변경 하고 2반환 합니다. [출처]@varSELECT @var := 1 + 1;@var


고마워 그들이 의미하는 것은 실제로 위의 대답보다 더 재미 있습니다.
Green

2

이봐, 난 그냥 그런 트릭이 필요했습니다-다른 방법으로 해결했습니다. 어쩌면 당신에게 도움이 될 것입니다. 이것은 확장 가능한 솔루션이 아니며 대규모 데이터 세트에는 매우 나쁩니다.

검색어를 두 부분으로 나눕니다.

먼저 업데이트하려는 행의 ID를 선택하여 임시 테이블에 저장하십시오.

둘째, update 문의 조건을로 변경하여 원래 업데이트를 수행하십시오 where id in temp_table.

또한 동시성을 보장하려면 이 두 단계 전에 테이블 을 잠근 다음 끝에 잠금을 해제해야합니다.

다시 말하지만 이것은으로 끝나는 쿼리에 대해 작동 limit 1하므로 임시 테이블을 사용하지 않고 대신 첫 번째 결과를 저장하는 변수를 사용합니다 select.

나는 항상 한 행만 업데이트하고 코드는 간단하다는 것을 알고 있기 때문에이 방법을 선호합니다.


2
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;

나는 id를 던져야했다. (dunno why) ... 또는 @uids 컨텐츠를 얻을 수 없다 (블롭이었다).


2

마지막으로 업데이트 된 행의 ID는 해당 행을 찾아 업데이트하기 위해 'updateQuery'에서 사용하는 것과 동일한 ID입니다. 따라서 원하는 ID를 저장하십시오.

last_insert_id()에 따라 다르지만 AUTO_INCREMENT마지막으로 업데이트 된 ID는 다릅니다 .


3
ID가 아닌 다른 속성 집합으로 업데이트를 수행하면 어떻게됩니까?
Sebas

2

내 해결책은 먼저 select 명령으로 "id"(@ uids)를 결정 하고이 id를 @uids로 업데이트 한 후입니다.

SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;

그것은 내 프로젝트에서 일했습니다.


1

삽입 만하고 동일한 세션에서 하나를 원한다면 peirix의 답변에 따라 수행하십시오. 수정을 수행하는 경우 가장 최근에 업데이트 된 항목을 저장하도록 데이터베이스 스키마를 수정해야합니다.

다른 세션에서 온 마지막 수정의 ID를 원할 경우 (즉, 현재 실행중인 PHP 코드에서 수행 한 세션이 아니라 다른 요청에 대한 응답으로 수행 된 세션) last_modified라는 테이블의 TIMESTAMP 열 ( 정보 는 http://dev.mysql.com/doc/refman/5.1/en/datetime.html 참조 )을 업데이트 한 후 last_modified = CURRENT_TIME을 설정하십시오.

이를 설정 한 후 다음과 같은 조회를 사용할 수 있습니다. SELECT id FROM table ORDER BY last_modified DESC LIMIT 1; 가장 최근에 수정 된 행을 가져옵니다.


-9

너무 긴 MySQL 코드가 필요하지 않습니다. PHP에서 쿼리는 다음과 같아야합니다.

$updateQuery = mysql_query("UPDATE table_name SET row='value' WHERE id='$id'") or die ('Error');
$lastUpdatedId = mysql_insert_id();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.