Forum: PC-Programmierung SQL-Frage: id automatisch lückenlos machen


von Flughafen (Gast)


Lesenswert?

Hallo,
ich habe eine Frage zu SQL. Und zwar habe ich eine Tabelle erzeugt und 
Datensätze darin gespeichert.
1
CREATE TABLE tbl_name (
2
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
3
inhalt TEXT
4
)DEFAULT CHARACTER SET utf8;
1
id inhalt
2
0  Ente
3
1  Hallo
4
2  Textfeldtest
5
3  MYSQL
6
4  Funktionierendes Beispiel
7
5  Hallo
Dann habe ich einen Datensatz gelöscht.
1
id inhalt
2
0  Ente
3
2  Textfeldtest
4
3  MYSQL
5
4  Funktionierendes Beispiel
6
5  Hallo
Wie kann man bei Löschung eines Datensatzes die id-Spalte automatisch 
lückenlos machen? Und wie wenn man schon eine Tabelle hat, in der schon 
rumgelöscht wurde?
1
id inhalt
2
0  Ente
3
1  Textfeldtest
4
2  MYSQL
5
3  Funktionierendes Beispiel
6
4  Hallo
So soll es danach aussehen.

von bluppdidupp (Gast)


Lesenswert?

Die Frage ist was da das Ziel ist.
Ich würde eine durchgehende Nummerierung on-the-fly beim Auslesen 
erzeugen, falls das nur irgendwo der Anzeige dienen soll.

von Flughafen (Gast)


Lesenswert?

bluppdidupp schrieb:
> Die Frage ist was da das Ziel ist.
> Ich würde eine durchgehende Nummerierung on-the-fly beim Auslesen
> erzeugen, falls das nur irgendwo der Anzeige dienen soll.

Das nicht. Ich möchte etwas Ordnung in der DB haben.Ich finde es nämlich 
nicht gut, wenn man 80 Datensätze mit id's bis 500 hat. Mit der Ausgabe 
hat das nur wenig zu tun.

von Karl H. (kbuchegg)


Lesenswert?

Flughafen schrieb:

> Wie kann man bei Löschung eines Datensatzes die id-Spalte automatisch
> lückenlos machen?

In einer Datenbank willst du das eigentlich nicht.
Wenn ein Datensatz mal eine id hat, dann hat er diese id und die ändert 
sich auch nicht.

Denn eine Datenbank lebt davon, dass sich Tabellen gegenseitig 
aufeinander beziehen können. Genau dazu braucht man ja diese id's um in 
einer Tabelle anzuzeigen, dass an sich auf die Informationen aus einer 
anderen tabelle mit einem Datensatz mit genau dieser id bezieht. Werden 
dort die id geändert, dann kommt alles durcheinander.

> So soll es danach aussehen.

Ich denke, du benutzt gerade das falsche Werkzeug für deine 
Problemstellung.

von Flughafen (Gast)


Lesenswert?

Karl Heinz schrieb:
> In einer Datenbank willst du das eigentlich nicht.
> Wenn ein Datensatz mal eine id hat, dann hat er diese id und die ändert
> sich auch nicht.

Und wenn man es nur einmal zum Aufräumen machen will?

von Karl H. (kbuchegg)


Lesenswert?

Flughafen schrieb:
> Karl Heinz schrieb:
>> In einer Datenbank willst du das eigentlich nicht.
>> Wenn ein Datensatz mal eine id hat, dann hat er diese id und die ändert
>> sich auch nicht.
>
> Und wenn man es nur einmal zum Aufräumen machen will?

Das will man auch nicht zum aufräumen machen.
Denn das bedeutet, dass man durch alle anderen Tabellen durchmuss, in 
denen diese id benutzt wird und das dort ebenfalls ändern muss. mal ganz 
abgesehen davon, dass es extrem aufwändig ist sicherzustellen, dass auch 
nicht zwischendurch es 2 Datensätze gibt, die dieselbe id haben.

Die id an sich interessiert niemanden, Das ist nur eine Zahl, über die 
Verknüpfungen quer über Tabellen hergestellt werden. Was die für einen 
numerischen Wert haben ist für einen Benutzer völlig uninteressant. Im 
Normalfall kriegt er die überhaupt nie zu Gesicht. Ihre einzige 
wesentliche Eigenschaft ist es, dass jeder Datensatz seine eigene 
eindeutige Nummer hat.

: Bearbeitet durch User
von datenbankhalbwissender (Gast)


Lesenswert?

Andere haben ja schon gesagt dass es eigentlich wurscht ist.

Willst du es dennoch so haben, gibt es je nach DB/Engine verschiedene 
Möglichkeiten:

* Index so einstellen dass Lücken wieder genutzt werden.
* Reindizieren
* Tabelle umkopieren und entspr. Flag setzen dass Index nicht 1:1
  übernommen wird sondern neu angelegt wird.

Hast du Referenzielle Integrität im Einsatz, dann kann es dir nach einer 
Reindizierung evt. die Referenzen zerschiessen. Das kann man auch 
einstellen, dass die automatisch aktuallisiert werden, ist halt wieder 
nach DB/Engine leicht anders.

Am besten du lässt die Finger davon, allein schon die Frage zeigt dass 
du davon keinen Plan hast. Du schiesst dir durch so eine Aktion 
höchstwahrscheinlich ins Knie.

von Karl H. (kbuchegg)


Lesenswert?

datenbankhalbwissender schrieb:

> Am besten du lässt die Finger davon, allein schon die Frage zeigt dass
> du davon keinen Plan hast. Du schiesst dir durch so eine Aktion
> höchstwahrscheinlich ins Knie.


:-)

Aus seinem anderen Parallelthread schliesse ich, dass er ein 
Programmierproblem dadurch lösen will, dass er seine Daten in eine DB 
laden will und dort dann so Dinge wie eine Löschaktion machen will, 
wobei ihm die DB dann eine Zählung fortlaufend halten soll.

Mein Fazit: Programmieren lernen und nicht versuchen, Tools wie 
Datenbanken dazu einzusetzen, seine eigenen Schwächen zu kaschieren. Vor 
allen Dingen dann nicht, wenn die Tools nicht dazu gebaut wurden, genau 
das Problem zu lösen, vor dem man gerade steht.

von Webseiten-Programmierer (Gast)


Lesenswert?

datenbankhalbwissender schrieb:
> Am besten du lässt die Finger davon, allein schon die Frage zeigt dass
> du davon keinen Plan hast. Du schiesst dir durch so eine Aktion
> höchstwahrscheinlich ins Knie.

Dann halt eben nicht. Was man noch tun kann ist ...

etwas sinnvolles tun z.B. 
Beitrag "HTML Javascript Drehfunktion" oder 
Beitrag "Fallblattanzeige Simulation"  oder
irgendwo sonst im Forum Fragen beantworten oder
hier noch eine Lösung schreiben;
oder
etwas unsinnvolles tun z.B. Viren installieren oder den PC abstürzen 
lassen (was aber nicht zu empfehlen ist).

von Bernd K. (prof7bit)


Lesenswert?

Flughafen schrieb:

> Das nicht. Ich möchte etwas Ordnung in der DB haben.Ich finde es nämlich
> nicht gut, wenn man 80 Datensätze mit id's bis 500 hat.

Das IST aber die Ordnung in jeder DB! Es gibt sogar welche bei denen 
besteht die ID aus 128 bit Zufallszahlen, die sind auch kein bisschen 
weniger ordentlich.

Außerdem ist es doch vollkommen gleichgültig wie die IDs der Datensätze 
aussehen, die bekommt der Nutzer eh nie zu Gesicht, die dienen (1) der 
Eindeutigkeit und (2) der Referenzierung von zugehörigen Datensätzen in 
verknüpften Tabellen, die DB nutzt sie um joins bei Abfragen über 
mehrere Tabellen ausführen zu können oder um die referentielle 
Integrität zu erzwingen. Ob die nun von 1 bis irgendwas oder von 9 
Billionen in 42er Schritten rückwärts zählen oder ob sie komplett 
zufällig sind ist vollkommen egal, hauptsache sie sind:

* eindeutig
* ändern sich nie

Sonst bricht das Chaos aus und das ist das exakte Gegenteil von Ordnung.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Natürlich kann man so eine Datenbank aufräumen. Hat zwar keinen Sinn, 
geht aber. Und zwar sogar zerstörungsfrei.

Dazu muss man sich nur einen View basteln, der ein select aus allen 
benötigten Spalten der Quelltabelle (bis auf die ID) in eine temporäre 
Tabelle macht - die sich wiederum ihre Datensatz-ID selbstbastelt, 
automatisch und aufsteigend. Die reicht der View zusammen mit den 
anderen Daten 'raus, und schon hat man eine Datenbank mit lückenloser, 
wenn auch komplett nutzloser ID.

Aber hey, Dinge aufräumen ist auch eine Kunstform:

http://www.keinundaber.ch/buecher_und_records/buecher/wehrli_die_kunst_aufzuraeumen/index.html

von Karl H. (kbuchegg)


Lesenswert?

Wenn wir ihm jetzt noch sagen, dass 'gelöschte' Datensätze in einer 
ordentlichen DB nicht wirklich gelöscht werden, sondern nur als gelöscht 
markiert sind, bricht wahrscheinlich eine Welt zusammen.

von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Wenn wir ihm jetzt noch sagen, dass 'gelöschte' Datensätze in einer
> ordentlichen DB nicht wirklich gelöscht werden, sondern nur als gelöscht
> markiert sind, bricht wahrscheinlich eine Welt zusammen.

in welcher ordentlichen DB sollte das der Fall sein?

MS-SQLServer löscht wirklich
Oracle löscht wirklich
DB2 löscht wirklich

oder meinst du etwas die NO-SQL Server?

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Karl Heinz schrieb:
>> Wenn wir ihm jetzt noch sagen, dass 'gelöschte' Datensätze in einer
>> ordentlichen DB nicht wirklich gelöscht werden, sondern nur als gelöscht
>> markiert sind, bricht wahrscheinlich eine Welt zusammen.
>
> in welcher ordentlichen DB sollte das der Fall sein?
>
> MS-SQLServer löscht wirklich
> Oracle löscht wirklich
> DB2 löscht wirklich

Echt?
D.h. die Files werden tatsächlich kleiner?

OK, dann hab ich mich geirrt und behaupte ab sofort das Gegenteil.

von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Echt?
> D.h. die Files werden tatsächlich kleiner?

das passiert selbst verständlich nicht beim löschen, es werden intern 
Pages freigeben, die dann für die nächsten Daten verwenden werden.
Wenn man will kann man den Platz durch Reorganisation der Daten 
freigeben.

Macht ja auch sinn, denn wenn man Daten am Anfang einer Datei löscht, 
rutscht das ende ja auch nicht nach.

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Karl Heinz schrieb:
>> Echt?
>> D.h. die Files werden tatsächlich kleiner?
>
> das passiert selbst verständlich nicht beim löschen, es werden intern
> Pages freigeben, die dann für die nächsten Daten verwenden werden.
> Wenn man will kann man den Platz durch Reorganisation der Daten
> freigeben.

:-)
genau darauf wollte ich hinaus.
OK. Schlecht ausgedrückt. Mein Fehler.

: Bearbeitet durch User
von Marcus W. (marcusaw)


Lesenswert?

Karl Heinz schrieb:
> Wenn wir ihm jetzt noch sagen, dass 'gelöschte' Datensätze in einer
> ordentlichen DB nicht wirklich gelöscht werden, sondern nur als gelöscht
> markiert sind, bricht wahrscheinlich eine Welt zusammen.

Je nach Anwendung macht es sogar Sinn, Datensätze nicht zu löschen, 
sondern nur zu "Flaggen", also ein Flag im jeweiligen Datensatz zu 
setzen.

Bei "normalen" Datenbanken die einige kB bis einige hundert Megabyte 
haben, kommt es jetzt auch nicht auf den Speicherplatz bzw den 
Memoryerbrauch an. Da setzt/löscht du dein Enable-Flag und gut. 
Irgendwann kommt dann Hausputz und man rutscht 10000 Datensätze auf ex 
raus, leert die Caches und gut. Gerade bei Szenarien mit etlichen 
simultanen Zugriffen ist das die sicherere und effizientere Lösung zum 
Drop.

: Bearbeitet durch User
von Konrad S. (maybee)


Lesenswert?

Bei so Winzlings-Datenbanken spielt es keine Rolle, aber mach so eine 
Reorganisation mal bei einer Terabyte-Datenbank, noch dazu im normalen 
Betriebsablauf. Der DB-Administrator wird umgehend geteert und gefedert.

von Peter II (Gast)


Lesenswert?

Konrad S. schrieb:
> Bei so Winzlings-Datenbanken spielt es keine Rolle, aber mach so eine
> Reorganisation mal bei einer Terabyte-Datenbank, noch dazu im normalen
> Betriebsablauf. Der DB-Administrator wird umgehend geteert und gefedert.

alles eine Frage der Hardware. Bei 400GB Datenbank ist es zumindest noch 
machbar.

von Konrad S. (maybee)


Lesenswert?

Natürlich ist es machbar, auch bei einer richtig großen DB. Nur wird der 
reguläre DB-Betrieb dadurch ausgebremst. Und wofür? Genau: für nichts 
und wieder nichts.

von Peter II (Gast)


Lesenswert?

Konrad S. schrieb:
> Natürlich ist es machbar, auch bei einer richtig großen DB. Nur wird der
> reguläre DB-Betrieb dadurch ausgebremst. Und wofür? Genau: für nichts
> und wieder nichts.

wenn man mal 30% der Datenmenge löschen muss, macht es durchaus sinn den 
Platz freizugeben.

von Konrad S. (maybee)


Lesenswert?

Hab ich anfangs auch mal gedacht, aber dann war da der Bumerang-Effekt: 
Die 30% kamen wieder. Platten nachschieben war deutlich einfacher und 
früher oder später eh unvermeidlich.

von Georg (Gast)


Lesenswert?

Konrad S. schrieb:
> Natürlich ist es machbar, auch bei einer richtig großen DB. Nur wird der
> reguläre DB-Betrieb dadurch ausgebremst.

Selbst bei seiner Mikro-Datenbank mit 80 Sätzen: soll die immer 
konsistent mit aufsteigenden Nummern sein, dann müssten beim Löschen von 
Satz 1 ja alle 79 anderen Sätze geändert werden. Dann fällt schon bei 80 
Datensätzen die Performance ins Bodenlose.

Georg

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Eine Id, die sich ständig ändert -- welchen Sinn hat die?

von Konrad S. (maybee)


Lesenswert?

Georg schrieb:
> Dann fällt schon bei 80
> Datensätzen die Performance ins Bodenlose.

... für die Dauer von ein paar Millisekunden. Das merkt keiner, wenn es 
ein paar tausend mal pro Tag passiert. Da sieht es bei einer großen DB 
anders aus. Und genau deswegen wird es nicht gemacht, auch nicht bei 
einer kleinen DB.

von RomanK (Gast)


Lesenswert?

Hallo Flughafen,

falls Dir dann kein Flieger abstürtzt und Du wirklich nur eine Tabelle 
hast nutze dies:

The syntax to enable a primary key using the ALTER INDEX statement in 
SQL Server (Transact-SQL) is:

ALTER INDEX constraint_name ON table_name
REBUILD;


Gruß

Roman

von Peter II (Gast)


Lesenswert?

RomanK schrieb:
> ALTER INDEX constraint_name ON table_name
> REBUILD;

das räumt aber nur den Index auf (Defragmentierung). Das hat keine 
Einfluss auf die IDs.

von Klaus P (Gast)


Lesenswert?

Flughafen schrieb:
> Und wenn man es nur einmal zum Aufräumen machen will?

Wenn du es unabhängig von dem verwendeten DBSM machen willst:
1. Entferne die FOREIGN KEY CONSTRAINTS, die auf deine Tabelle verweisen
2. Lege eine neue Tabelle mit gleichen Spalten an und kopiere die Daten 
(außer der ID) hier hinein - die ID wird jetzt neu fortlaufend vergeben 
- achte dabei auf die Reihenfolge
3. Lege eine Mapping-Tabelle an, die die IDs der alten und der neuen 
Tabelle zuordnet
4. Lösche die alte Tabelle und lege sie neu an (damit
5. Kopiere alle Daten aus den neuen Tabelle hier hinein (wieder ohne die 
ID) - achte auf die Reihenfolge
6. Pflege mit UPDATE die Felder in den andere Tabellen, die auf die ID 
verweisen (benutze dabei die Mapping-Tabelle)
7. Lege die FOREIGN KEY CONSTRAINTS wieder an

Alle anderen Wege hängen von dem verwendeten DBMS ab.

Wenn du alles das zukünftig vermeiden willst, verwende GUIDs (UUID) als 
PRIMARY KEY und führe ein Sortierungsfeld ein. Ist zwar nicht ganz so 
gut lesbar, funktioniert aber. Niemand stört sich daran, dass es sinnlos 
ist, nach GUIDs zu sortieren.

Je nach DBMS reicht auch ein einfaches ON UPDATE CASCADE in den FOREIGN 
KEYs. Aber nicht bei allen DBMSen lassen sich AUTOINCREMENT Felder mit 
UPDATE ändern.

von Klaus P (Gast)


Lesenswert?

Peter II schrieb:
> Karl Heinz schrieb:
>> Echt?
>> D.h. die Files werden tatsächlich kleiner?
>
> das passiert selbst verständlich nicht beim löschen, es werden intern
> Pages freigeben, die dann für die nächsten Daten verwenden werden.
> Wenn man will kann man den Platz durch Reorganisation der Daten
> freigeben.
>
> Macht ja auch sinn, denn wenn man Daten am Anfang einer Datei löscht,
> rutscht das ende ja auch nicht nach.

AUTOVACUUM bei PostgreSQL und die entsprechend anders bezeichneten (aber 
gleichartigen) Funktionen bei anderen DBMSen sind seit einigen Jahren 
Standard. Früher musste man dafür manuell ein externes oder internes 
REBUILD durchführen - im Grunde nichts anderes als eine Sicherung und 
Wiedereinlesen. Das muss man aber schon seit geraumer Zeit nicht mehr.

von Jens G. (jensig)


Lesenswert?

@ Peter II (Gast)

>Karl Heinz schrieb:
>> Wenn wir ihm jetzt noch sagen, dass 'gelöschte' Datensätze in einer
>> ordentlichen DB nicht wirklich gelöscht werden, sondern nur als gelöscht
>> markiert sind, bricht wahrscheinlich eine Welt zusammen.

>in welcher ordentlichen DB sollte das der Fall sein?

>MS-SQLServer löscht wirklich
>Oracle löscht wirklich
>DB2 löscht wirklich

>oder meinst du etwas die NO-SQL Server?

Also in punkto DB2 (zumindest auf Windows/Unix) hat KH recht - die Daten 
werden nicht wirklich gelöscht, sondern deren Speicherplatz (Slot) nur 
als solche markiert, bzw. als wieder frei markiert.

von Peter II (Gast)


Lesenswert?

Jens G. schrieb:
> Also in punkto DB2 (zumindest auf Windows/Unix) hat KH recht - die Daten
> werden nicht wirklich gelöscht, sondern deren Speicherplatz (Slot) nur
> als solche markiert, bzw. als wieder frei markiert.

was hat löschen mit Speicher-Freigeben zu tun? Eine Festplatte wird auch 
nicht kleiner wenn man Daten löscht.

Wenn man es genau nimmt, kann man überhaupt keine Daten löschen maximal 
überschreiben.

von Jens G. (jensig)


Lesenswert?

@Peter II (Gast)

>Jens G. schrieb:
>> Also in punkto DB2 (zumindest auf Windows/Unix) hat KH recht - die Daten
>> werden nicht wirklich gelöscht, sondern deren Speicherplatz (Slot) nur
>> als solche markiert, bzw. als wieder frei markiert.

>was hat löschen mit Speicher-Freigeben zu tun? Eine Festplatte wird auch
>nicht kleiner wenn man Daten löscht.

Das habe ich auch nicht behauptet, und um mich auch nicht auf das 
Verkleinern zu beziehen, habe ich KH's Erstaunen

>Echt?
>D.h. die Files werden tatsächlich kleiner?

gar nicht erst mitzitiert.
Du hattest behauptet, daß
> MS-SQLServer löscht wirklich
> Oracle löscht wirklich
> DB2 löscht wirklich
was eben zumindest bei DB2 nicht stimmt (und bei den anderen wohl auch 
nicht).
(ich gehe davon aus, daß Du meintest "löscht wirklich" = "überschreibt 
wirklich")

von Peter II (Gast)


Lesenswert?

Jens G. schrieb:
> gar nicht erst mitzitiert.
> Du hattest behauptet, daß
>> MS-SQLServer löscht wirklich
>> Oracle löscht wirklich
>> DB2 löscht wirklich
> was eben zumindest bei DB2 nicht stimmt (und bei den anderen wohl auch
> nicht).
> (ich gehe davon aus, daß Du meintest "löscht wirklich" = "überschreibt
> wirklich")

versteht nicht was du sagen willst.

Diese Datenbanken löschen die Daten in dem sie intern den 
Speicherbereich freigeben, wenn danach neue Datensätze angelegt werden, 
werden diese Bereiche überschrieben.

Das verstehe ich auch unter löschen. Wenn sie dagegen nur "versteckt" 
werden und mit normalen mitteln wieder sichtbar gemacht werden können, 
das ist es kein löschen.

von Jens G. (jensig)


Lesenswert?

Vielleicht reden wir aneinander vorbei, und meinen doch daselbe.

Wenn wir von Löschen in einer Datenbank reden, dann meint man Löschen im 
Sinne von SQL, daß der Datensatz damit unsichtbar bzw. nicht mehr 
auffindbar geworden ist. Für normales SQL ist der Record unsichtbar, 
wenn einmal commited.

Man könnte ja jetzt mal theoretisieren, und sich mal verschiedene 
Löschstrastegien vorstellen, wie eine Datnebank das Löschen 
bewerkstelligt. Dann kann jeder sich raussuchen, was er wohl gemeint 
hat:

1.
Der Record wird nur als gelöscht markiert, dessen Speicherplatz aber 
noch nicht als frei markiert (nicht freigegeben), kann also noch nicht 
wiederbenutzt werden, bzw. ist noch blockiert. Für die db ist der Record 
für spezielle interne Zwecke noch referenzierbar, aus SQL Sicht gilt er 
aber schon als gelöscht (wird tatsächlich in db2 unter bestimmten 
Bedingungen gemacht).

2.
Der Record wird als gelöscht markiert, und kann auch wiederbenutzt 
werden für neue Daten. Die Referenzen im Inhaltsverzeichnis der Page 
bleiben aber noch erhalten. Solange die Daten aber nicht durch neue 
Daten überschrieben wurden, sind die gelöschten Daten (intern, auserhalb 
der SQL-Welt) noch referenzierbar, auffindbar, wiederherstellbar (das 
Prinzip der FAT, weil in deren Kettenstruktur einfach einfacher).

3.
Die Referenz des Records wird aus dem Inhaltverzeichnis der Page 
gelöscht, ist also nicht mehr direkt referenzierbar (und damit als 
freigegeben markiert). Die Daten selbst sind aber immer noch da, können 
also auf der Platte immer noch gefunden werden. Machen vermutlich die 
meisten Datenbanken.

4.
Die Referenz des Records wird aus dem Inhaltverzeichnis der Page 
gelöscht,
und der vom Datensatz belegte Platz wird explizit mit irgendwas 
überschrieben im zuge des Löschvorgangs. Jetzt sind die Daten wirklich 
nicht mehr sichtbar bzw. wiederhestellbar. Ob das manche db's machen 
(können), weis ich nicht.

5.
Die Referenz des Records wird aus dem Inhaltverzeichnis der Page 
gelöscht,
und der freigewordenen Platz (bzw. ein Äquivalent dessen an anderer 
Stelle )wird an das Filesystem wieder als freier Platz zurückgegeben. So 
machen es z.B. einfache Text-Editoren. Bei einer db natürlich schwerlich 
vorstellbar direkt beim Löschen, weil nicht vereinbar mit der internen 
Pagestruktur, und weil sowas Performance kosten würde. Bei einem 
Reorganisieren kann das dann aber auch gemacht werden.

6. ich nehme den Hammer und ... (ok, das macht i.d.R. keinen nutzbaren 
Platz mehr frei (höchstens im freigewordenen Plattenslot), aber die 
Daten sind wenigstens weg ;-)

Wenn ich das jetzt auf Euer Gespräch anwende, dann hat KH Variante 2 
oder 3 gemeint, Du widersprachst, und meintest Variante 4 (zumindest 
habe ich es so verstanden, weil Du von "wirklich löschen" schriebst), 
woraufhin KH schlußfolgerte, es sei 5 (wie auch immer). Da das alles 
also irgendwie die falsche Richtung nahm, hatte ich mal nebenbei so 
eingeworfen, 3 ist richtig, um wieder für Klarheit zu schaffen (hat wohl 
nicht so richtig geklappt :-( Inzwischen glaube ich aber auch, du 
meintest wohl doch 3.

von A. B. (funky)


Lesenswert?

Unterscheidet doch einfach, ob der Datensatz auf Applikationsebene bzw. 
Anwendungsebene(durch ein gelöscht-Flag) "gelöscht" wird, oder auf 
Datenbankebene.
Die die Datenbankebene das Löschen genau implementiert, ist doch dabei 
eher zweitrangig. Wenn ich ein "DELETE" ausführe komme ich nicht mehr an 
den Eintrag ran, ausser die DB liefert dafür noch Tools mit.

Bei der Flag Geschichte steht der Datensatz normal in der DB, wird nicht 
überschrieben oder ähnliches, sondern dem Nutzer einfach nicht angezeigt

von Georg (Gast)


Lesenswert?

A. B. schrieb:
> Bei der Flag Geschichte steht der Datensatz normal in der DB, wird nicht
> überschrieben oder ähnliches, sondern dem Nutzer einfach nicht angezeigt

Das war beim seligen DBase und allen Abkömmlingen so, aber das ist auch 
heute noch verbreitet, sonst würden einem z.B. Mailprogramme nicht immer 
wieder mit der Frage auf die Nerven fallen, ob die Daten reorganisiert 
werden sollen - dann erst werden die gekennzeichneten Datensätze 
entfernt, bzw. nicht mit kopiert. Und dann wird auch die Datei kleiner.

Das hat ja auch nicht nur Nachteile, sondern erfüllt die 
Papierkorb-Funktion - bis zur Reorganistaion kann der Admin 
versehentlich gelöschte Sätze zurückholen.

Georg

von Markus (Gast)


Lesenswert?

Hi,

Jens G. schrieb:
> Wenn wir von Löschen in einer Datenbank reden, dann meint man Löschen im
> Sinne von SQL, daß der Datensatz damit unsichtbar bzw. nicht mehr
> auffindbar geworden ist. Für normales SQL ist der Record unsichtbar,
> wenn einmal commited.
solange eine andere Session diese Daten durch einen bereits geöffneten 
Cursor noch lesen wird, bleibt alles beim alten, trotz Commit der 
löschenden Session: Consistent Read.

Grüße, Markus

von Bahnhof (Gast)


Lesenswert?

in tsql
UPDATE tbl_name set
tb1.id = tb2.new_id
from tbl_name as tb1
cross apply (select id, inhalt, rownumber() over(order by id asc ) ) as 
new_id from tbl_name) as tb2
where tb1.id = tb2.id

so ungefähr, ungetestet

viel Spass

von S-Bahn-Station (Gast)


Lesenswert?

Fehlt nur noch U-Bahn-Station :)

Transact-Sql (tsql) hat aber nicht jeder. Geht das in normalem SQL?

von Flughafen (Gast)


Lesenswert?

S-Bahn-Station schrieb:
> Fehlt nur noch U-Bahn-Station :)

Leider darf man in einem Topic nicht mit 2 Namen schreiben, sonst würde 
ich mich umbenennen!

S-Bahn-Station schrieb:
> Transact-Sql (tsql) hat aber nicht jeder. Geht das in normalem SQL?

Wie richtet man den tsql ein?

von Peter II (Gast)


Lesenswert?

S-Bahn-Station schrieb:
> Transact-Sql (tsql) hat aber nicht jeder. Geht das in normalem SQL?

der code  Bahnhof  geht auch nicht wirklich in T-SQL dafür sind zu viele 
fehler drin.

Aber selbst wenn er stimmen würde, löst es nicht das Hauptproblem. Es 
müssen auch alle Tabelle geupdatet werden, wie auf die Tabelle 
verweisen.

Und das geht mit allgemeinen SQL nur wie schon von hier 
Beitrag "Re: SQL-Frage: id automatisch lückenlos machen" 
geschrieben.

von S-Bahn-Station (Gast)


Lesenswert?

Bahnhof schrieb:
> so ungefähr, ungetestet

Peter II schrieb:
> S-Bahn-Station schrieb:
>> Transact-Sql (tsql) hat aber nicht jeder. Geht das in normalem SQL?
>
> der code  Bahnhof  geht auch nicht wirklich in T-SQL dafür sind zu viele
> fehler drin.
>
> Aber selbst wenn er stimmen würde, löst es nicht das Hauptproblem. Es
> müssen auch alle Tabelle geupdatet werden, wie auf die Tabelle
> verweisen.
>
> Und das geht mit allgemeinen SQL nur wie schon von hier
> Beitrag "Re: SQL-Frage: id automatisch lückenlos machen"
> geschrieben.

Der Code funktioniert also aus mehreren Gründen nicht:
1. Fehler
2. Selbst ohne Fehler macht er nicht das gewünschte.

Teste beim nächsten mal einfach deinen Code vorher aus, Bahnhof. Ein 
echter Bahnhof kann ja nicht einfach die Weichen stellen, ohne auf den 
Zugplan zu achten!

von Bahnhof (Gast)


Lesenswert?

Ihr seid Helden. Ich habe doch gesagt ich habe es nicht getestet, da ich 
kein TSQl gerade zur Hand habe. Konzeptuelle Fehler sehe ich gerade 
nicht, lasse mich aber gerne eines besseren belehren. Vielleicht gibts 
ein Syntaxerror? Jeder mit TSQL Zugang kann gerne darauf aufbauen. Ich 
wollte ein paar Ideen zur Lösung anbringen nämlich die rownumber und das 
cross apply.

Dass nicht jeder TSQL haben muss, ist mir klar, wurde aber auch nicht 
gesagt, welcher Dialekt in Ordnung ist. Wenn es um den kleinsten 
gemeinsamen Nenner des SQL geht, dann kann ich leider nicht ohne 
Erstellung und Nutzung temporaere Tabelle dienen.

TSQL ist Transact SQL und eine Erweiterung genutzt von Microsoft in 
ihren SQL Servern. Die Express Variante ist kostenlos von jedermann 
nutzbar.

von Peter II (Gast)


Lesenswert?

Bahnhof schrieb:
> Konzeptuelle Fehler sehe ich gerade
> nicht, lasse mich aber gerne eines besseren belehren

also das du einfach eine Tabelle ohne die anderen Tabellen zu ändern die 
darauf zeigen finde ich schon einen konzeptuelle Fehler.

von Bahnhof (Gast)


Lesenswert?

In der Ausgansfrage sind keine anderen Tabellen angesprochen worden.
Über die Sinnhaftigkeit dieser Unternehmung wurde in diesem Thread schon 
ausgiebig gestritten. Zu Recht wie ich auch denke.

Trotzdem ist die Lösung dieser Aufgabe interessant.
Wenn anderen Tabellen existieren, würde ich eine temporäre Tabelle 
erstellen die sowohl alte als auch neue id enthaelt. Davon ausgehend 
kann der Primärschlüssel der besagten Tabelle geändert werden, als auch 
alle Fremdschlüssel.

von Bahnhof (Gast)


Lesenswert?

S-Bahn-Station schrieb:
> Der Code funktioniert also aus mehreren Gründen nicht:
> 1. Fehler
> 2. Selbst ohne Fehler macht er nicht das gewünschte.
>
> Teste beim nächsten mal einfach deinen Code vorher aus, Bahnhof. Ein
> echter Bahnhof kann ja nicht einfach die Weichen stellen, ohne auf den
> Zugplan zu achten!

Ich möchte noch erwähnen, dass Donnerstag und Freitag keine SBahn kam, 
auch Sonnabend wars das gleiche.

1. kleine Fehler berichtigt
2. widerlegt

UPDATE tbl_name set
id = tb2.new_id
from tbl_name as tb1
cross apply (select id, inhalt, row_number() over(order by id asc ) as 
new_id
from tbl_name) as tb2
where tb1.id = tb2.id


Wenn es ohne TSQL sein soll dann wie gesagt am einfachsten in eine 
temporäre Tabelle. Die Herausforderung ist die neue Nummerierung. Eine 
virtuelle Spalte erstellen,
in TSQL mit rownumber oder autoincrement Spalte
mit MySQL kannst Du eine Inkrementanweisung einbauen siehe hier
http://blog.sqlauthority.com/2014/03/08/mysql-generating-row-number-for-each-row-using-variable/
bei Sybase gibts auch ein Autoincrement Identity Spalte.

Gibt eigentlich in jedem Dialekt was. Gehts auch mit "normalen" SQL? Mir 
fällt nichts ein. Kennt wer was?

von Philipp K. (philipp_k59)


Lesenswert?

Bahnhof schrieb:
> Trotzdem ist die Lösung dieser Aufgabe interessant.
> Wenn anderen Tabellen existieren, würde ich eine temporäre Tabelle
> erstellen die sowohl alte als auch neue id enthaelt

Jopp sehe ich auch so.. Ich würde dem Fragesteller mal Sortierung und 
Limits in Abfragen oder allgemeine Grundlagen empfehlen.

Da wäre eher eine "eigene" Indexspalte nützlich die man ab und zu nach 
echtem Index sortiert und via cron oder bei insert updatet.

Gogole sagt:
SET @rank:=0;
update Table
set meineid=@rank:=@rank+1

von S-Bahn-Station (Gast)


Lesenswert?

Noch ne Idee dazu:
Die Tabelle wurde mit id angelegt: (vermutlich) id INT (UNSIGNED) NOT 
NULL AUTO_INCREMENT PRIMARY KEY. Wenn man jetzt die id löscht und dann 
neu anlegt, würde dann neu gezählt werden?

von Flughafen (Gast)


Lesenswert?

Stimmt, funktioniert! Wie einfach eine Lösung sein kann ...
Neu anlegen funktioniert wie folgt:
1
ALTER TABLE `katalog` ADD `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.