it-swarm.com.de

Auto Increment nach dem Löschen in MySQL

Ich habe eine MySQL-Tabelle mit einem Primärschlüsselfeld, das AUTO_INCREMENT auf ..__ hat. Nachdem ich andere Beiträge gelesen habe, habe ich Leute mit dem gleichen Problem und mit vielfältigen Antworten bemerkt. Einige empfehlen, diese Funktion nicht zu verwenden, andere geben an, dass sie nicht "behoben" werden können.

Ich habe:

table: course
fields: courseID, courseName

Beispiel: Anzahl der Datensätze in der Tabelle: 18. Wenn ich die Datensätze 16, 17 und 18 lösche, würde ich davon ausgehen, dass der nächste eingegebene Datensatz die Kurs-ID 16 hat. Es wird jedoch 19 sein, da die zuletzt eingegebene Kurs-ID 18 war.

Meine SQL-Kenntnisse sind nicht verblüffend. Gibt es trotzdem eine Möglichkeit, diese Anzahl mit einer Abfrage (oder einer Einstellung in der phpMyAdmin-Benutzeroberfläche) zu aktualisieren oder zu aktualisieren?

Diese Tabelle bezieht sich auf andere in einer Datenbank.


Angesichts all dieser Ratschläge habe ich mich entschlossen, dieses "Problem" zu ignorieren. Ich werde einfach Datensätze löschen und hinzufügen, während das automatische Inkrement seine Arbeit erledigen lässt. Ich denke, es spielt keine Rolle, was die Zahl ist, da sie nur als eindeutige Kennung verwendet wird und keine (wie oben erwähnt) business Bedeutung hat.

Für diejenigen, die ich möglicherweise mit meinem ursprünglichen Beitrag verwechselt habe: Ich möchte dieses Feld nicht verwenden, um zu wissen, wie viele Datensätze ich habe. Ich wollte nur, dass die Datenbank ordentlich aussieht und etwas mehr Konsistenz hat.

60
OmidTahouri

Was Sie zu tun versuchen, klingt gefährlich, da dies nicht die beabsichtigte Verwendung von AUTO_INCREMENT ist.

Wenn Sie wirklich den niedrigsten unbenutzten Schlüsselwert finden möchten, verwenden Sie AUTO_INCREMENT nicht und verwalten Sie Ihre Schlüssel manuell. Dies ist jedoch KEINE empfohlene Praxis.

Machen Sie einen Schritt zurück und fragen Sie "warum müssen Sie Schlüsselwerte wiederverwenden?". Bieten unsignierte INT (oder BIGINT) nicht genügend Schlüsselplatz an? 

Wirst du wirklich mehr als 18,446,744,073,709,551,615 eindeutige Aufzeichnungen im Laufe der Laufzeit deiner Anwendung haben?

66
Dolph
ALTER TABLE foo AUTO_INCREMENT=1

Wenn Sie die neuesten Einträge gelöscht haben, sollte dies so eingestellt werden, dass der nächstniedrigste verfügbare Eintrag verwendet wird. Solange noch keine 19 vorhanden ist, wird das automatische Inkrementieren durch das Löschen von 16-18 auf 16 zurückgesetzt.


EDIT: Ich habe etwas über phpmyadmin verpasst. Sie können es auch dort einstellen. Gehen Sie zum Tabellenbildschirm und klicken Sie auf die Registerkarte Operationen. Dort gibt es ein AUTOINCREMENT Feld, das Sie manuell einstellen können.

33
monksp

Primäre Autoincrement-Schlüssel in der Datenbank werden zur eindeutigen Identifizierung einer bestimmten Zeile verwendet und sollten keine business - Bedeutung erhalten. Lassen Sie den Primärschlüssel so wie er ist und fügen Sie eine weitere Spalte hinzu, die beispielsweise courseOrder genannt wird. Wenn Sie dann einen Datensatz aus der Datenbank löschen, möchten Sie möglicherweise eine zusätzliche UPDATE-Anweisung senden, um die courseOrder-Spalte aller Zeilen zu dekrementieren, für die courseOrder größer ist als die, die Sie gerade löschen.

Als Randbemerkung sollten Sie niemals den Wert eines Primärschlüssels in einer relationalen Datenbank ändern, da es andere Tabellen geben könnte, die auf ihn als Fremdschlüssel verweisen, und wenn er geändert wird, können referenzielle Einschränkungen verletzt werden.

16
Darin Dimitrov

Versuchen :

SET @num: = 0;

UPDATE your_table SET id = @num: = (@ num + 1);

ALTER TABLE tableName AUTO_INCREMENT = 1;

Dadurch wird der automatisch hinzugefügte Wert zurückgesetzt und dann jede Zeile gezählt, während ein neuer Wert dafür erstellt wird.

beispiel: vorher

  • 1: erster Wert hier
  • 2: zweiter Wert hier
  • X: gelöschter Wert
  • 4: Der Rest der Tabelle
  • 5: Der Rest des Restes ..

die Tabelle zeigt also das Array an: 1,2,4,5

Beispiel: AFTER (wenn Sie diesen Befehl verwenden, erhalten Sie)

  • 1: erster Wert hier
  • 2: zweiter Wert hier
  • 3: Der Rest der Tabelle
  • 4: der restliche rest

Keine Spur des gelöschten Werts, und der Rest des Inkrementierten wird mit dieser neuen Zählung fortgesetzt.

ABER

  1. Wenn irgendwo in Ihrem Code etwas von dem automatisch hinzugefügten Wert verwendet wird, verursacht diese Zuordnung möglicherweise Probleme.
  2. Wenn Sie diesen Wert nicht in Ihrem Code verwenden, sollte alles in Ordnung sein.
8
Claod

Sie sollten sich nicht auf die ID AUTO_INCREMENT verlassen, um Ihnen mitzuteilen, wie viele Datensätze Sie in der Tabelle haben. Sie sollten SELECT COUNT(*) FROM course verwenden. IDs dienen dazu, den Kurs eindeutig zu identifizieren, und können als Referenz in anderen Tabellen verwendet werden. Daher sollten Sie die IDs nicht wiederholen und nicht versuchen, das Feld für die automatische Erhöhung zurückzusetzen.

3
Mike Sherov

sie können die IDs wie folgt auswählen:

set @rank = 0;
select id, @rank:[email protected]+1 from tbl order by id

das Ergebnis ist eine Liste von IDs und deren Positionen in der Sequenz.

sie können die IDs auch so zurücksetzen:

set @rank = 0;
update tbl a join (select id, @rank:[email protected]+1 as rank from tbl order by id) b
  on a.id = b.id set a.id = b.rank;

sie können auch die erste nicht verwendete ID wie folgt ausdrucken:

select min(id) as next_id from ((select a.id from (select 1 as id) a
  left join tbl b on a.id = b.id where b.id is null) union
  (select min(a.id) + 1 as id from tbl a left join tbl b on a.id+1 = b.id
  where b.id is null)) c;

nach jedem Insert können Sie das auto_increment zurücksetzen:

alter table tbl auto_increment = 16

oder den ID-Wert beim Einfügen explizit setzen:

insert into tbl values (16, 'something');

in der Regel ist dies nicht erforderlich, Sie haben count(*) und können in Ihren Ergebnissätzen eine Rangfolge erstellen. Ein typisches Ranking könnte sein:

set @rank = 0;
select a.name, a.amount, b.rank from cust a,
  (select amount, @rank:[email protected]+1 as rank from cust order by amount desc) b
  where a.amount = b.amount

kunden gereiht nach ausgegebenem Betrag.

2
user262976

Ich kam hierher und suchte nach einer Antwort auf die Titelfrage "MySQL - Auto Increment after delete", aber ich konnte nur eine Antwort darauf in den Fragen finden

Mit etwas wie:

DELETE FROM table;
ALTER TABLE table AUTO_INCREMENT = 1;

Beachten Sie, dass Darin Dimitrovs Antwort wirklich gut erklären AUTO_INCREMENT und seine Verwendung. Schauen Sie dort nach, bevor Sie etwas tun, das Sie vielleicht bereuen.

PS: Die Frage selbst ist mehr "Why you need to recycle key values?" und Dolphs Antwort decke das ab.

2
Michel Ayres

Ich habe eine sehr einfache, aber knifflige Methode. 

Beim Löschen einer Zeile können Sie die IDs in einer anderen temporären Tabelle beibehalten. Wenn Sie danach neue Daten in die Haupttabelle einfügen, können Sie IDs aus der temporären Tabelle suchen und auswählen. Verwenden Sie hier also eine Überprüfung. Wenn die temporäre Tabelle keine IDs hat, berechnen Sie die maximale ID in der Haupttabelle und setzen Sie die neue ID auf: new_ID = old_max_ID+1.

NB: Sie können hier die Funktion zum automatischen Inkrementieren nicht verwenden.

1
arefin2k

Ich kann mir viele Szenarien vorstellen, in denen Sie dies möglicherweise tun müssen, insbesondere während eines Migrations- oder Entwicklungsprozesses. Zum Beispiel musste ich gerade eine neue Tabelle erstellen, indem ich zwei vorhandene Tabellen (als Teil eines komplexen Einrichtungsprozesses) miteinander verknüpfte, und dann musste ich nach dem Ereignis einen Primärschlüssel hinzufügen. Sie können die vorhandene Primärschlüsselspalte löschen und dann tun.

ALTER TABLE my_table ADD `ID` INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`ID`);

Für ein Live-System ist dies keine gute Idee, insbesondere wenn andere Tabellen mit Fremdschlüsseln darauf verweisen.

1
Peter Smartt

Es gibt tatsächlich einen Weg, das zu beheben. Zuerst löschen Sie die automatisch hinzugefügte Primärschlüsselspalte und fügen sie dann wie folgt erneut hinzu:

ALTER TABLE table_name DROP column_name;
ALTER TABLE table_name ADD column_name int not null auto_increment primary key first;
1
Geni Jaho

Sie können Ihre MySQL-Clientsoftware/Ihr Skript verwenden, um anzugeben, von wo aus der Primärschlüssel nach dem Löschen der erforderlichen Datensätze beginnen soll.

0
Sarfraz

Möglicherweise möchten Sie nach dem Löschen einen Trigger ausführen, damit Sie den Wert der automatischen Inkrementierung und den ID-Wert aller Zeilen aktualisieren können, die nicht so aussehen, wie Sie es sehen wollten.

Sie können also mit derselben Tabelle arbeiten, und das automatische Inkrement wird automatisch festgelegt, wenn Sie eine Zeile löschen, die durch den Trigger korrigiert wird.

0
Aloui Khalil

Es ist definitiv nicht zu empfehlen. Wenn Sie über eine große Datenbank mit mehreren Tabellen verfügen, haben Sie möglicherweise eine Benutzer-ID als ID in Tabelle 2 gespeichert. Wenn Sie Tabelle 1 neu anordnen, wird die beabsichtigte Benutzer-ID wahrscheinlich nicht die beabsichtigte Tabelle 2-ID sein.

0
Joshua Omwoyo

hier ist eine Funktion, die Ihr Problem behebt

    public static void fixID(Connection conn, String table) {

    try {
        Statement myStmt = conn.createStatement();
        ResultSet myRs;
        int i = 1, id = 1, n = 0;
        boolean b;
        String sql;

        myRs = myStmt.executeQuery("select max(id) from " + table);
        if (myRs.next()) {
            n = myRs.getInt(1);
        }
        while (i <= n) {
            b = false;
            myRs = null;
            while (!b) {
                myRs = myStmt.executeQuery("select id from " + table + " where id=" + id);
                if (!myRs.next()) {
                    id++;
                } else {
                    b = true;
                }
            }

            sql = "UPDATE " + table + " set id =" + i + " WHERE id=" + id;
            myStmt.execute(sql);
            i++;
            id++;
        }

    } catch (SQLException e) {
        e.printStackTrace();
    }
}
0
dani bilel
if($id == 1){ // deleting first row
            mysqli_query($db,"UPDATE employees  SET id=id-1 WHERE id>1");
        }
        else if($id>1 && $id<$num){ // deleting middle row
            mysqli_query($db,"UPDATE employees  SET id=id-1 WHERE id>$id");
        }
        else if($id == $num){ // deleting last row
            mysqli_query($db,"ALTER TABLE employees AUTO_INCREMENT = $num");
        }
        else{
            echo "ERROR";
        }

        mysqli_query($db,"ALTER TABLE employees AUTO_INCREMENT = $num");
0
Vaso Nadiradze

Was Sie zu tun versuchen, ist sehr gefährlich. Denken Sie sorgfältig darüber nach. Es gibt einen sehr guten Grund für das Standardverhalten der automatischen Erhöhung. 

Bedenken Sie:

Ein Datensatz wird in einer Tabelle gelöscht, die eine Beziehung zu einer anderen Tabelle hat. Der entsprechende Datensatz in der zweiten Tabelle kann aus Prüfgründen nicht gelöscht werden. Dieser Datensatz wird von der ersten Tabelle verwaist. Wenn ein neuer Datensatz in die erste Tabelle eingefügt wird und ein sequentieller Primärschlüssel verwendet wird, ist dieser Datensatz jetzt mit dem Orphan verknüpft. Natürlich ist das schlecht. Durch die Verwendung einer automatisch inkrementierten PK wird immer eine ID garantiert, die noch nie zuvor verwendet wurde. Das bedeutet, dass Waisenkinder Waisenkinder bleiben, was korrekt ist. 

0