Primärschlüssel neu ordnen

Xarfai

Mitglied
Hi,

Ich habe derzeit folgendes Problem. Ich habe eine Datenbank und klar ID als Primärschlüssel und auf auto_increment. Nehmen wir nun an ich lösch z.B. den Datensatz mit der ID 2 und erstelle danach einen neuen Datensatz geht er bei 3 weiter. oder wenn ich später bei 10 Datensätzn zB nr 8 lösche dann ist ja nur 1-7 und dann 9&10 da. Ich will aber das der die ID fortlaufend hält. Hätte einer ne Idee wie man da eine Funktion realisieren könnte die das automatisch durchprüft und die datensätze dann wieder richtig aneinanderreit?

Hab mir selber schon folgende Sachen überlegt:

a) Datenbanktabelle komplett auslesen zwischenspeichern
Datenbanktabelle löschen
Datenbanktabelle neuanlegen (ID ist beim startwert)
Datenbanktabelle mit Daten füllen

Diese Möglichkeit denke ichmal funktioniert nur is sie sehr langsam umständlich und noch dazu Traffic lastig

b) id inner for schleife durchzählen wenn eine Lücke da ist dann zähle 1 weiter und setz die id auf -1. und das dann für alle Datensätze. Sprich sone Abart von Bubblesort. Nur... da rechnet der sich nachner zu Tode glaub ich.

Vielleicht hat ja jemand ne Idee. Danke =D .
 
hm naja weil ich die ID ausgebe als Zeilen Nummer ok gut das könnt ich auch mitner For schleife machn und dann beim link für die einzelne Zeile halt dann ...php?id=$id schon klar. Aber ich würde das halt auch gerne mal für die zukunft wissen ;D man will ja dazulernen. Und so lücken sehn einfach doof aus -_- ok wenns nu 1,,3 anstatt 1,2,3 ist ok aber wenn nu zB 100,16512312 oder so das sieht bekloppt aus -_- *bissel übertrieben ich weiss.
 
Eine Möglichkeit wäre, die ID nach dem Löschen eines Datensatzes neu zu ordnen:
Code:
UPDATE
        …
  SET
        `id` = `id` - 1
  WHERE
        `id` > x
Zusätzlich muss dann aber noch der „AUTO_INCREMENT“-Wert angepasst werden:
Code:
ALTER TABLE … AUTO_INCREMENT = (SELECT COUNT(*) - 1 FROM …)
Ob letzteres überhaupt funktioniert, weiß ich nicht.
 
Naja was du dabei vergisst ist aber der Fall wenn man mittendrin löscht ... so würde es funktionieren wenn ich immer nur den letzten Wert löschen würde ... *weitergrübel* ist echt schon schwer irgendwie *grins
 
Xarfai hat gesagt.:
Naja was du dabei vergisst ist aber der Fall wenn man mittendrin löscht ... so würde es funktionieren wenn ich immer nur den letzten Wert löschen würde ... *weitergrübel* ist echt schon schwer irgendwie *grins
Wieso das denn? Die erste Abfrage sorgt doch gerade dafür, dass alle Datensätze mit einer ID größer als der des gelöschten Datensatzes angepasst werden.
 
hmm stimmt aber mir ist grad nochne Möglichkeit eingefallen... Ich könnte doch auch einfach die datensätze zählen und dann ID inenr for schleife durchrattern lassen und neueintragen / zeile..
 
Ich habe es hingekriegt für alle die es interessiert hier der Code...
*eignet sich vielleicht sogar fürnen Tutorial :D*
*Update: auto_increment wird jetzt auch upgedatet*

Und nun hier nochmal eine kleine Erklärung für Sinn und Zweck dieses Scripts:

Ich wollte halt mal wissen ob man diese "Lücken" beseitigen kann die beim löschen von Datensätzen auftreten sofern man auf auto_increment gestellt hat. Das dieses Script ungeeignet ist wenn man relationen benutzt weiss ich. Aber wenn ich relationen bentuze benutz ich sowieso lieber einen Timestamp. Also bitte nicht hier den beitrag zutexten von wegen ich untermauere irgendnen Sinn.

Danke =)

Wer das Script haben will Quellcode steht wie gesagt unten ;)
Copyright bleibt aber bitte drinne danke =)



PHP:
<?php

 /* Copyright by Xarfai 2006 */
 
 /* Primärschlüssel ordnen */

 $datenbanktabelle = "bitteinfügen";

 /* Ermittlung des kleinsten Werts */
 $query = "SELECT MIN(id) FROM ".$datenbanktabelle;
 $sql = mysql_query($query);
 $min = mysql_result($sql,0);
 
 /* Deklarierung der Array Laufzeit Variable
    $al steht für arraylaenge */
 $al = 1;
 
 /* Auslesen der vorhandenen IDs aus der Datenbank 
    Schreiben der Daten in einen Array
 */
 $query= mysql_query("SELECT id FROM ".$datenbanktabelle." ORDER by id ASC");
 while($daten = mysql_fetch_array($query)) 
 {
  $id=$daten[id];
  $array[$al] = $id;
  $al++;
 }

/* Abfrage ob eine ID 1 vorhanden ist wenn nicht dann wird die kleinste genommen */

 if ($min != 1)
  {
   $lauf = 1;
  }
 else
  {
   $lauf = $min;
  }

 /* 
    Schleife zum Updaten 
    Die Schleife läuft sooft durch wie die Anzahl der Daten im Array beträgt
    dabei Updatet sie die Datenbanktabelle so das eine vortlaufende Nummerierung entsteht.
    Ausserdem erfolgt eine Ausgabe des Codes ;) (kann man auch rausnehmen ich fands aber
    sehr hilfreich um zu gucken ob der auch wirklich das tut was ich will
 */

 for($anzahl = 2; $anzahl <= $al; $anzahl++)
  {
     $query = "UPDATE ".$datenbanktabelle." SET id = ".$lauf." WHERE id = ".$array[$lauf];
     $sql = mysql_query($query);
     
  
     echo "UPDATE ".$datenbanktabelle." SET id = ".$lauf." WHERE id = ".$array[$lauf];
     $lauf++;
     echo "<br>";
  }

   /* Nachträglich hinzugefügt ... Diese Zeile sorgt dafür das auto_increment danach auch fein säuberlich    weiterzählt */
 
   $query = "ALTER TABLE `".$datenbanktabelle."` AUTO_INCREMENT = ".$lauf;
   $sql = mysql_query($query);

   echo "ALTER TABLE `".$datenbanktabelle."` AUTO_INCREMENT = ".$lauf;

 @mysql_close;

?>
 
Zuletzt bearbeitet:
Das wiederspricht doch mal wieder gänzlich dem Prinzip einer ID. Eine ID ist ein eindeutiger Identifikator eines Datensatzes. Wenn du die den Datensatz löschst, ist er weg, genau so auch die ID.
War dieser Datensatz irgendwo referenziert, würdest du deinen kompletten Datenbestand durcheinander bringen. Die Datenbank kannst du damit wegschmeißen.

Als Zeilennummerierung sollten IDs auch nicht genutzt werden. Je nach Bedingung kommen andere Datensätze zurück und die Nummerierung wäre auch nicht mehr lückenlos.
Oracle, MSSQL und andere DBMS stelle Funtionen zur Verfügung, die die Zeile des Datensatzes in der aktuellen Abfrage liefern. So was wird es doch auch in MySQL geben. Wenn nicht, wäre es immer noch besser, beim Anzeigen einen Counter mitlaufen zu lassen, der als Zeilennummerierung fungiert.

//EDIT:
Wer suchet, der findet auch. (google liefert übrigens 3,3 Mio Ergebnis für das Problem mit der Zeilennummer)
http://dev.mysql.com/doc/refman/5.1/en/mysql-row-tell.html so was zum Beispiel
 
Zuletzt bearbeitet:
naja 1. wollt ich das selber schreiben 2. Wenn ich mit relationen arbeite werde ich dieses sortieren nicht verwenden ;) trotzdem danke.
 
Zurück