Mysql'de bir sonraki otomatik artış kimliği nasıl alınır


114

MySQL'deki sonraki kimliği tabloya eklemek için nasıl alınır

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

1
bir auto_incrementsütun kullanın
knittl

İster misiniz sonraki kimliği, veya şu anda ekleme olduğunu satırın id? Yani, ödeme kodunun sonundaki kimlik, ödeme kodunun saklandığı satırın kimliği mi olmalı?
Mike

şu anda
eklediğim

6
Bu durumda, değerleri eklediğinizde değil, aldığınızda birleştirin. Böylesi çok daha kolay ve yanlış kimliği almayı veya bir güncelleme çalıştırma zorunluluğunu ortadan kaldırırsınız - güncellemenin çalıştırılma şansı olmadan önce eklediğiniz satır başka bir müşteri tarafından istenirse ne olacağını düşünün: müşteri geçersiz bir ödeme koduyla sonuçlanır. Düşük trafikli bir sistemde bu gerçekleşmeyebilir, ancak risk alma noktasını görmüyorum.
Mike

... veya @binaryLV'nin işaret ettiği gibi, kaynak kilitleme de sorunu çözebilir. Bakınız: dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Mike

Yanıtlar:


12

Kullanım LAST_INSERT_ID()SQL sorgusu.

Veya

mysql_insert_id()PHP kullanarak almak için de kullanabilirsiniz .


13
@Sarfraz: Soru söylediğin gibi SON değil SONRAKİ kimliği ile ilgiliydi . LAST_INSERT_ID()
Felipe Pereira

1
Tablodaki satırlar silinirse maksimum yanlış olur
peterchaula

sadece '17'den bir not - mysql * işlevleri kullanımdan kaldırıldı - yukarıda yapılabilirmysqli_insert_id
treyBake

bunu cevap olarak kim işaretledi? soru son değil sonraki kimlik numarasıyla ilgili.
Amit Şah

253

Kullanabilirsiniz

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

veya information_schema kullanmak istemiyorsanız bunu kullanabilirsiniz

SHOW TABLE STATUS LIKE 'table_name'

İlk iki seçenek için teşekkürler .. Ama üçüncüsü sadece iki numara PHP'den çağrıldı .. Bunu büyük veri tabanlarında neyin daha hızlı yaptığından emin değilim ...
Gerard ONeill

1
@GerardONeill Kaldırdı
ravi404

3
information_schema.tables'dan verileri almak için bir önbellek kullanıldığından, bu çözüm artık mysql 8 için çalışmıyor.
Bruno

1
@Bruno bir referans gönderebilir misin?
mvorisek

1
Dev.mysql.com/doc/refman/8.0/en/…TABLES.AUTO_INCREMENT önbelleğe alınan bu resmi belge durumu . Mysql blogunda da bununla ilgili birkaç gönderi var, ancak bahsettikleri sistem güncelliğini yitirmiş görünüyor: mysqlserverteam.com/… mysqlserverteam.com/…
Bruno

50

Bir sonraki otomatik artış değerini şu şekilde elde edebilirsiniz :

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

Not gerektiğini değil tabloyu değiştirmek için kullanabilir, yerine otomatik bunu bir auto_increment sütununu kullanın.
Sorun, last_insert_id()geriye dönük olması ve dolayısıyla mevcut bağlantı içinde garanti edilebilmesidir.
Bu bebek potansiyeldir ve bu nedenle bağlantı başına benzersiz değildir ve güvenilemez.
Yalnızca tek bir bağlantı veritabanında çalışır, ancak bugün tek bağlantılı veritabanları yarın birden çok bağlantı veritabanı olma alışkanlığına sahiptir.

Görmek: SHOW TABLE STATUS


5
Eksik oy vermedim, ancak son otomatik artan değeri kullanmaya teşebbüs etmekteki sorun, onu kullanmaya geldiğinizde bunun son değer olmayabileceğidir - SEÇME ve sonraki INSERT ne kadar hızlı yapılırsa yapılsın.
Mike

@Mike, ya tek sorgu ile yapılırsa? Gibi bir şey insert into table_name (field1, field2) select 'constant', auto_increment from information_schema.tables where table_name = 'table_name'? after insertTetikleyicide güncellemeyi kullanırdım ve last_insert_id()yine de ...
binaryLV

1
@binaryLV: SELECT ve INSERT arasındaki boşluk ne kadar küçükse, değerin değişme şansı o kadar az olur, ancak bu tamamen göz ardı etmez. Veritabanında dakikada binlerce isabetli bir sistem hayal edin - değerin değişme şansı çarpıcı biçimde artar. Tablo veya satır kilitleme, tek bir sorgu olarak yapılırsa bunu önleyebilir, ancak bu, veritabanı motorunun iyi belgelenmemiş olabilecek belirli bir davranışına dayanır. Ben de olsaydı bir sonraki ile giderdim UPDATE. Ancak ikisini görüntüleme zamanında birleştirmeyi ve tüm güçlüğü kurtarmayı tercih ederim.
Mike

3
SHOW TABLE STATUSdatabase namesonrasını FROMve 'table name pattern'sonrasını görmeyi bekler LIKE.
x-yuri

2
information_schema.tables'dan verileri almak için bir önbellek kullanıldığından, bu çözüm artık mysql 8 için çalışmıyor.
Bruno

15

Bu, MySQL veritabanı için otomatik artış değerini döndürecektir ve diğer veritabanlarını kontrol etmedim. Lütfen başka bir veritabanı kullanıyorsanız, sorgu sözdiziminin farklı olabileceğini unutmayın.

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

İnformation_schema.tables WHERE table_name = 'your_table_name' ve table_schema = 'your_database_name';
LJay

10

En üstteki cevap bir çözüm için PHP MySQL_ kullanıyor , bunu başarmak için güncellenmiş bir PHP MySQLi_ çözümünü paylaşacağımı düşündüm . Bu örnekte hata çıktısı yok!

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

Tabloda gelen sonraki Otomatik artışı başlatır.


information_schema.tables'dan verileri almak için bir önbellek kullanıldığından, bu çözüm artık mysql 8 için çalışmıyor.
Bruno

9

PHP'de şunu deneyebilirsiniz:

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

VEYA

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

5
En yüksek kimliğe sahip kayıt düşürülürse, ilk yöntemi aklınızda bulundurun, daha sonra bırakılanın sahip olduğu id ile yeni bir kayıt oluşturacaksınız.
Tom Jenkinson

ve önceki anahtar başka bir masada kullanılmışsa ve hala orada tutulursa, çok garip bir sihirle karşılaşabilirsiniz
Tebe

son eklenen kaydı düşürürseniz ilki yanlış kimliği döndürür,
Ali Parsa

6

Çözüm:

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", Veri Tabanımızın adıdır


5

Basit bir sorgu işe yarar SHOW TABLE STATUS LIKE 'table_name'



3

Kimliği girerken kullanamazsınız, ihtiyacınız da yoktur. MySQL, bu kaydı eklediğinizde kimliği bile bilmiyor. Sadece kurtarabilecek "sahf4d2fdd45"içinde payment_codemasa ve kullanım idve payment_codedaha sonra.

Ödeme kodunuzun içinde kimliğe sahip olması için gerçekten ihtiyacınız varsa, kimliği eklemek için ekten sonraki satırı GÜNCELLEYİN.


+1 Bunu biraz daha açık hale getirmek için: Bir sütundan 'en son' değeri alırsanız, yalnızca onu aldığınız anda en son değer olacağı garanti edilir. Bu değeri sonraki bir eklemede kullanmaya geldiğinizde en son değer olmayabilir. Otomatik artış sütunu durumunda, kimliği aldığınız zaman ile başka bir yere eklediğiniz zaman arasında her zaman başka bir değerin eklenme şansı vardır. Henüz eklediğiniz bir satıra başvuruyorsanız, LAST_INSERT_ID () kullanılması uygundur. Benzersiz bir değer sağlamaya çalışıyorsanız, öyle değildir.
Mike

@cularis, MySQL sonraki auto_increment kimliğini biliyor, information_schema.tablestabloda listeleniyor .
Johan

1
@faressoft: Fikir, benzersiz bir dize artı bu ödeme kodunu içeren satırın kimliğini içeren bir ödeme koduna sahip olmaksa, satırı aldığınızda ikisini birleştirin - ya a ile ya SELECT ... CONCAT(payment_code, id)da uygulama kodunuzda. Hatta , uygulamanızdaki her SELECT'te CONCAT hakkında endişelenmeden her zaman doğru değeri döndürmek için SELECTa içine bile sarabilirsiniz VIEW.
Mike

3

Bir sonraki artımlı kimliğe ne için ihtiyacınız var?

MySQL, tablo başına yalnızca bir otomatik artış alanına izin verir ve benzersizliği garantilemek için birincil anahtar olması da gerekir.

Bir sonraki giriş kimliğini aldığınızda, sahip olduğunuz değer yalnızca bu işlemin kapsamında olduğundan, onu kullandığınızda kullanılamayabileceğini unutmayın. Bu nedenle, veritabanınızdaki yüke bağlı olarak, bu değer bir sonraki istek geldiğinde zaten kullanılmış olabilir.

Daha sonra hangi otomatik artış değerini atayacağınızı bilmenize gerek olmadığından emin olmak için tasarımınızı gözden geçirmenizi öneririm.


Kimliği gerektiren uygulama türünü varsaymak iyi bir fikir değildir. Şu anda üzerinde çalıştığım gibi, bir sonraki artımlı kimliğe ihtiyaç duyan ve alınan değerin başka bir komut dosyasına atanma tehlikesi olmayan uygulamalar var.
JG Estiot

3

Ne yaptığınızı yeniden düşünmenizi öneririm. Bu özel bilginin gerekli olduğu tek bir kullanım durumunu hiç yaşamadım. Bir sonraki kimlik çok özel bir uygulama detayıdır ve ACID güvenli olduğundan emin değilim.

Eklediğiniz satırı son id ile güncelleyen basit bir işlem yapın:

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;

Böyle bir kullanım durumunu söyleyebilirim, bir üretim sorununu teşhis etmeye çalışıyorum, bu yüzden bir tablodaki son satırın gerçekten son satır olup olmadığını veya bundan sonra bir şekilde silinen bir satırın eklenip eklenmediğini bulmam gerekiyor. içinde bir auto_increment alanı var, bu yüzden bu bilgiyi bularak satırın silinip silinmediğini veya hiç eklenmediğini söyleyebilirim.
Usman

1
Bu sizin için işe yarayabilir, ancak bu konuda herhangi bir garantiniz olduğunu düşünmediğim için buna güvenmem: dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html " AUTO_INCREMENT sütunu çok sütunlu bir dizinin parçası olduğunda), herhangi bir gruptaki en büyük AUTO_INCREMENT değerine sahip satırı silerseniz AUTO_INCREMENT değerleri yeniden kullanılır. "
Markus Malkusch

Teşekkürler, yararlı bilgiler, aynı zamanda paylaşılan bağlantınıza göre auto_increment manuel olarak bir numara ekleyerek sıfırlanabilir, bu nedenle evet güvenilir değildir.
Usman

2

Bunu yapmadan önce MySQL'e bağlanmanız ve bir veritabanı seçmeniz gerekir.

$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 ()" kullanın. mysql_insert_id (), gerçekleştirilen son sorguya göre hareket eder, değeri üreten sorgudan hemen sonra mysql_insert_id () öğesini çağırdığınızdan emin olun.

Aşağıda kullanım örneği verilmiştir:

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

Umarım yukarıdaki örnek yararlıdır.


Teşekkürler bunun farkındayım.
Bay Javed Multani


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

Verimliliğinden şüphe duysam da% 100 güvenilir


Ben de bunun en basit yaklaşım olduğuna katılıyorum. Neden olumsuz oy aldığınızdan emin değilim, ama olumlu oyla telafi edeceğim.
tekrarlayın

İşlemin gerekliliğinden bahsetmedim, işlemin içine sarmazsanız, bu kod en kısa zamanda gerçek yüklemeyi karşılar.
Tebe

1
Ya son satır silindiyse? Veya birden çok son satır silindi mi?
Liam W

Sorunsuz, serbest bırakılan anahtarlar, siz açıkça belirtmediğiniz sürece kullanılmaz
Tebe

1

ravi404 cevabını kullanarak:

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 Hash oluşturmak için ekleme sorgunuzda kullanarak. ex .:

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

Bu her zaman işe yarar mı? Aynı anda iki eklenti olursa bir yarış koşulu var mı?
Jmons

0

Otomatik artış ofsetinizin 1 DEĞİLDİR olması durumunda @ ravi404 iyileştirmesi:

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 motoru her zaman 1 ofseti dikkate alıyor gibi görünüyor. Bu nedenle, bu varsayımı atmanız ve ardından @@ auto_increment_offset'in isteğe bağlı değerini eklemeniz veya 1: IFNULL (@@ auto_increment_offset, 1) değerine varsayılan değer eklemeniz gerekir.


0

Benim için işe yarıyor ve basit görünüyor:

 $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

Yapabildiğiniz $last_idzaman tekrar tekrar atama yapmak oldukça gereksizdir DESC. Kişisel whileblok yararsız çalışma yükleri yaptı.
Tiw

evet, doğru ... Mükemmel olmadığını yeni fark ettim ... :( son kişi kimliği tekrar edebilir, daha önce silinmişse ... :(
Toncsiking

0

Doğru AUTO_INCREMENT döndürmezse, deneyin:

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

BD'de tablo için bu temiz önbellek

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.