mysql에서 다음 자동 증가 ID를 얻는 방법


114

mysql에서 다음 ID를 가져와 테이블에 삽입하는 방법

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

1
auto_increment열 사용
knittl 2011-07-20

다음 ID 를 원하십니까 , 아니면 현재 삽입중인 행의 ID 를 원하십니까 ? 즉, 결제 코드 끝에있는 ID가 결제 코드가 저장된 행의 ID 여야합니까?
Mike

현재 삽입중인 행의 id
faressoft 2011-07-20

6
이 경우 값을 삽입 할 때가 아니라 검색 할 때 값을 연결하십시오. 그렇게하는 것이 훨씬 쉬우 며 잘못된 ID를 얻거나 업데이트를 실행해야하는 것을 배제합니다. 업데이트를 실행할 기회가 있기 전에 방금 삽입 한 행을 다른 클라이언트에서 요청하면 어떻게 될지 생각해보십시오. 클라이언트 유효하지 않은 결제 코드로 끝납니다. 트래픽이 적은 시스템에서는 발생하지 않을 수도 있지만 위험을 감수 할 시점은 알 수 없습니다.
Mike

... 또는 @binaryLV가 지적했듯이 리소스 잠금도 문제를 해결할 수 있습니다. 참조 : dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Mike

답변:


12

LAST_INSERT_ID()SQL 쿼리에서 사용 합니다.

또는

mysql_insert_id()PHP를 사용 하여 가져올 수도 있습니다 .


13
@Sarfraz : 질문은 당신이 언급 했듯이 마지막이 아닌 NEXT ID 에 관한 것이 었습니다 . LAST_INSERT_ID()
Felipe Pereira

1
행이 테이블에서 삭제 된 경우 최대 잘못된 것
peterchaula

'17에서 불과 메모 - MySQL은 * 기능이 사용되지 않습니다 - 이상 수행 할 수 있습니다mysqli_insert_id
treyBake

누가 이것을 답변으로 표시 했습니까? 질문은 마지막이 아닌 다음 삽입 ID에 관한 것입니다.
Amit Shah

253

당신이 사용할 수있는

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

또는 information_schema를 사용하지 않으려면 이것을 사용할 수 있습니다.

SHOW TABLE STATUS LIKE 'table_name'

처음 두 가지 옵션에 감사드립니다.하지만 세 번째 옵션은 PHP에서 호출 한 두 번째입니다. 대규모 데이터베이스에서 더 빠르게 만드는 이유가 무엇인지 확실하지 않습니다.
Gerard ONeill

1
@GerardONeill을 제거
ravi404

3
캐시가 information_schema.tables에서 데이터를 검색하는 데 사용되기 때문에이 솔루션은 mysql 8에서 더 이상 작동하지 않습니다.
Bruno

1
@Bruno 참조를 게시 할 수 있습니까?
mvorisek

1
TABLES.AUTO_INCREMENT캐시 된 이 공식 문서 상태 는 dev.mysql.com/doc/refman/8.0/en/… 입니다. Mysql 블로그에도 여러 게시물이 있지만 그들이 언급 한 시스템 변수는 구식 인 것 같습니다 : mysqlserverteam.com/… mysqlserverteam.com/…
Bruno

50

다음 을 수행 하여 다음 자동 증가 값을 얻을 수 있습니다 .

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

이를 사용하여 테이블을 변경 해서는 안되며 , 대신 auto_increment 열을 사용하여 자동으로 수행하십시오.
문제는 last_insert_id()회고 적이므로 현재 연결 내에서 보장 될 수 있다는 것 입니다.
이 아기는 장래성이므로 연결마다 고유하지 않으며 신뢰할 수 없습니다.
단일 연결 데이터베이스에서만 작동하지만 오늘날 단일 연결 데이터베이스는 내일 여러 연결 데이터베이스가되는 습관이 있습니다.

보다: SHOW TABLE STATUS


5
나는 그것을 downvote하지 않았지만 마지막 자동 증가 값을 사용하려는 시도의 문제는 SELECT 및 후속 INSERT가 아무리 빨리 수행 되더라도 사용하게 될 때 마지막 값이 아닐 수 있다는 것입니다.
Mike

@Mike, 단일 쿼리로 수행되면 어떻게됩니까? 같은 뭔가 insert into table_name (field1, field2) select 'constant', auto_increment from information_schema.tables where table_name = 'table_name'? 나는 after insert트리거 에서 업데이트를 사용 하고 last_insert_id(), 그래도 ...
binaryLV

1
@binaryLV : SELECT와 INSERT 사이의 간격이 작을수록 값이 변경 될 가능성이 적지 만 완전히 배제하지는 않습니다. 데이터베이스에서 분당 수천 개의 히트가있는 시스템을 상상해보십시오. 값이 변경 될 가능성이 급격히 증가합니다. 테이블 또는 행 잠금은 단일 쿼리로 수행되는 경우이를 방지 할 수 있지만 이는 잘 문서화되지 않은 데이터베이스 엔진의 특정 동작에 의존하고 있습니다. 나도 가지고 UPDATE있다면 후속으로 갈 것입니다 . 하지만 표시 시간에 두 개를 연결하고 모든 번거 로움을 덜어주고 싶습니다.
Mike

3
SHOW TABLE STATUSdatabase name이후 FROM'table name pattern'이후 를 볼 것으로 예상됩니다 LIKE.
X-유리

2
캐시가 information_schema.tables에서 데이터를 검색하는 데 사용되기 때문에이 솔루션은 mysql 8에서 더 이상 작동하지 않습니다.
Bruno

15

이것은 MySQL 데이터베이스에 대한 자동 증분 값을 반환하며 다른 데이터베이스와 확인하지 않았습니다. 다른 데이터베이스를 사용하는 경우 쿼리 구문이 다를 수 있습니다.

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 = 'your_table_name'및 table_schema = 'your_database_name';
LJay

10

최고의 답변은 솔루션으로 PHP MySQL_ 을 사용하며 , 이를 달성하기 위해 업데이트 된 PHP MySQLi_ 솔루션을 공유 할 것이라고 생각 했습니다. 이 예제에는 오류 출력이 없습니다!

$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'];

테이블에서 다음 자동 증분을 시작합니다.


캐시가 information_schema.tables에서 데이터를 검색하는 데 사용되기 때문에이 솔루션은 mysql 8에서 더 이상 작동하지 않습니다.
Bruno

9

PHP에서는 다음을 시도 할 수 있습니다.

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

또는

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

5
가장 높은 ID를 가진 레코드가 삭제 된 경우 첫 번째 방법을 염두에두면 삭제 된 레코드가 가지고 있던 ID로 새 레코드를 만듭니다.
Tom Jenkinson 2015 년

이전 키가 다른 테이블에서 사용되었지만 여전히 거기에 보관되어 있다면 매우 이상한 마법으로 끝날 수 있습니다
Tebe

마지막으로 삽입 한 레코드를 삭제하는 경우 첫 번째 반환 잘못된 아이디,
알리 파사

6

해결책:

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"은 데이터베이스의 이름입니다.


5

간단한 쿼리는 SHOW TABLE STATUS LIKE 'table_name'



3

삽입하는 동안 ID를 사용할 수 없으며 필요하지도 않습니다. MySQL은 해당 레코드를 삽입 할 때 ID도 알지 못합니다. 당신은 절약 할 수 "sahf4d2fdd45"에서 payment_code테이블을 사용 id하고 payment_code나중에.

지불 코드에 ID가 있어야 실제로 필요한 경우 삽입 후 행을 업데이트하여 ID를 추가하십시오.


+1 좀 더 명확하게하기 위해 : 열에서 '최신'값을 가져 오면 해당 값을 가져 오는 정확한 순간에만 최신 값이 보장됩니다. 후속 삽입에서 해당 값을 사용하게되면 최신 값이 아닐 수 있습니다. 자동 증가 열의 경우 ID를 검색 한 시간과 다른 곳에 삽입 한 시간 사이에 다른 값이 추가되었을 가능성이 항상 있습니다. 방금 삽입 한 행을 참조하는 경우 LAST_INSERT_ID ()를 사용하는 것이 좋습니다. 고유 한 값을 보장하려는 경우에는 그렇지 않습니다.
Mike

@cularis, MySQL은 다음 auto_increment ID를 알고 있으며 information_schema.tables표에 나열되어 있습니다.
Johan

1
@faressoft : 아이디어가 고유 한 문자열과 해당 결제 코드가 포함 된 행의 ID를 포함하는 결제 코드를 갖는 것이라면 행을 검색 할 때 두 가지를 결합하십시오 (으로 SELECT ... CONCAT(payment_code, id)또는 애플리케이션 코드에서). 당신도 포장 할 수 SELECTA의 VIEW당신은 항상 당신의 응용 프로그램에서 모든 SELECT에서 CONCAT에 대한 걱정없이, 올바른 값을 반환 그래서.
Mike

3

다음 증분 ID가 필요한 것은 무엇입니까?

MySQL은 테이블 당 하나의 자동 증가 필드 만 허용하며 고유성을 보장하려면 기본 키 여야합니다.

다음 삽입 ID를 받으면 보유한 값이 해당 트랜잭션의 범위 내에 있기 때문에 사용할 때 사용하지 못할 수 있습니다. 따라서 데이터베이스의로드에 따라 다음 요청이 들어올 때 해당 값이 이미 사용되었을 수 있습니다.

다음에 할당 할 자동 증가 값을 알 필요가 없는지 확인하기 위해 디자인을 검토하는 것이 좋습니다.


ID가 필요한 응용 프로그램의 종류를 가정하는 것은 좋지 않습니다. 다음 증분 ID가 필요한 현재 작업중인 애플리케이션과 같은 애플리케이션이 있으며 검색된 값은 다른 스크립트에 할당 될 위험이 없습니다.
JG Estiot

3

나는 당신이하는 일을 다시 생각할 것을 제안합니다. 나는 특별한 지식이 필요한 단일 사용 사례를 경험 한 적이 없습니다. 다음 ID는 매우 특별한 구현 세부 사항이며 ACID 안전을 고려하지 않습니다.

마지막 ID로 삽입 된 행을 업데이트하는 간단한 트랜잭션을 만듭니다.

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;

이러한 사용 사례 중 하나를 말할 수 있습니다. 프로덕션 문제를 진단하려고합니다. 따라서 테이블의 마지막 행이 실제로 마지막 행인지 아니면 그 뒤에 추가 된 행이 있는지 확인해야합니다. 그 안에 auto_increment 필드가 있으므로이 정보를 찾아 행이 삭제되었는지 또는 추가되지 않았는지 결론을 내릴 수 있습니다.
Usman

1
그것은 당신에게 효과가 있을지도 모르지만 나는 당신이 그것에 대한 어떤 보장도 없다고 생각하기 때문에 그것에 의존하지 않을 것입니다 : dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html " AUTO_INCREMENT 컬럼이 다중 컬럼 인덱스의 일부인 경우, 그룹에서 AUTO_INCREMENT 값이 가장 큰 행을 삭제하면 AUTO_INCREMENT 값이 재사용됩니다. "
Markus Malkusch

감사합니다. 유용한 정보도 공유 링크에 따라 auto_increment를 수동으로 숫자를 삽입하여 재설정 할 수 있으므로 신뢰할 수 없습니다.
Usman

2

이 작업을 수행하려면 먼저 MySQL에 연결하고 데이터베이스를 선택해야합니다.

$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

"mysql_insert_id ()"를 사용하십시오. mysql_insert_id ()는 마지막으로 수행 된 쿼리에 대해 작동하므로 값을 생성하는 쿼리 직후에 mysql_insert_id ()를 호출해야합니다.

다음은 사용 예입니다.

<?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());
    ?>

위의 예가 유용하기를 바랍니다.


알고 감사합니다.
Mr.Javed Multani


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

생산성은 의심 스럽지만 100 % 신뢰할 수 있습니다


나도 이것이 가장 간단한 접근 방식이라는 데 동의합니다. 왜 당신이 반대표를 받았는지 확실하지 않지만 나는 찬성표로 상쇄하겠습니다.
recurse

트랜잭션의 필요성에 대해서는 언급하지 않았습니다. 트랜잭션 내부에 래핑하지 않으면이 코드는 실제로드를 충족하는 한 끔찍합니다.
Tebe 2016-07-25

1
최신 행이 삭제되면 어떻게됩니까? 아니면 여러 최신 행이 삭제 되었습니까?
Liam W

명시 적으로 지정하지 않는 한 발행되지 않은 해제 된 키는 사용되지 않습니다.
Tebe

1

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

삽입 쿼리에서 사용하여 SHA1 해시를 만듭니다. 전의.:

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

항상 작동합니까? 두 개의 인서트가 동시에 발생하면 경쟁 조건이 있습니까?
Jmons 2016-10-27

0

자동 증가 오프셋이 1이 아닌 경우 @ ravi404 개선 :

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) : db 엔진은 오프셋 1을 고려하는 것 같습니다. 따라서이 가정을 버리고 옵션 값인 @@ auto_increment_offset을 추가하거나 기본값을 1로 설정해야합니다. IFNULL (@@ auto_increment_offset, 1)


0

나를 위해 그것은 작동하고 간단 해 보입니다.

 $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

$last_id당신이 할 수있을 때 반복적 으로 할당 하는 것은 매우 불필요합니다 DESC. 귀하의 while블록은 쓸모없는 작업을 많이했습니다.
Tiw

네, 맞아요 ... 완벽하지 않다는 걸 방금 깨달았어요 ... :( 이전에 삭제 되었다면 마지막 ID를 반복 할 수 있습니다 ... :(
Toncsiking

0

올바른 AUTO_INCREMENT를 반환하지 않으면 시도해보십시오.

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

BD에서 테이블에 대한 캐시 지우기

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.