ID´s aus SQL Filtern und löschen.
Martin19
- php
Guten Tag,
habe da mal eine Frage.
Ich will per php script Daten die in einer SQL Tabelle sind anhand ihrer ID auswählen und Löschen.
Er soll nur die 30 neuesten Einträge behalten.
Ich habe mir schon was gedacht nur weiß ich nicht ob das ganz so richtig ist.
Ich muss zuerst Abfragen welche ID der neueste Beitrag hat.
<?php
$abfrage = "SELECT id FROM TABELLE";
$ergebnis = mysql_query($abfrage);
$maxid = mysql_num_rows($ergebnis);
$menge;
?>
soweit richtig?
Dann muss ich die Menge in eine Lösch prozedur bringen.
<?php
$loeschen = "DELETE FROM links WHERE id < '$maxid - 30'";
$loesch = mysql_query($loeschen);
?>
würde das so funktionieren?
Mfg Martin
würde das so funktionieren?
Nein, da du nicht davon ausgehen kannst, dass die ID fortlaufend ist. Zudem würde das nur beim ersten Mal funktioneren und alle weitere Male um jeweils 30 Datensätze in die Hose gehen.
Btw: Warum machst du das ganze nicht in einem SQL-Statement?
Hole dir alle Datensätze die (absteigend sortiert) mit einem Offset von 30 Datensätzen beschränkt auf einen. dann lösche alle, die eine kleinere ID haben als das ergebnis.
Das kannst du bequem in ein DELETE-Statement mit Subselect verpacken.
Faustregel: mache NIEMALS irgendwas in eine Scriptsprache, wenn es die Datenbank ohnehin kann - es ist absolut unsinnig (und Performanceraubend) die Daten hin und herzuschaufeln).
Hole dir alle Datensätze die (absteigend sortiert) mit einem Offset von 30 Datensätzen beschränkt auf einen. dann lösche alle, die eine kleinere ID haben als das ergebnis.
Sprich so?
<?php
session_start();
$verbindung = mysql_connect ("localhost",
"", "")
or die ("keine Verbindung möglich.
Benutzername oder Passwort sind falsch");
mysql_select_db("")
or die ("Die Datenbank existiert nicht.");
$abfrage = "SELECT ID FROM links ORDER BY ID DESC LIMIT 1";
$ergebnis = mysql_query($abfrage);
$row = mysql_fetch_object($ergebnis);
echo $row->ID - 10;
$del = $row->ID -10;
echo $del;
$loeschen = "DELETE FROM links WHERE ID < $del";
$loesch = mysql_query($loeschen);
?>
»» Hole dir alle Datensätze die (absteigend sortiert) mit einem Offset von 30 Datensätzen beschränkt auf einen. dann lösche alle, die eine kleinere ID haben als das ergebnis.
Sprich so?
Nein
$abfrage = "SELECT ID FROM links ORDER BY ID DESC LIMIT 1";
$loeschen = "DELETE FROM links WHERE ID < $del";
Damit hast du erst wieder 2 Abfragen (da wo eine reicht, bzw. eine mit Subquery). Aber du hast wieder ein logisches Problem
Du holst dir alle ID aus der Tabelle, verkehrt herum sortiert beschränkt auf einen Datensatz. Damit löscht du nun alle bis auf einen.
Die Geschichte mit dem Offset fehlt noch (die LIMIT-Optimierung solltest du dir nochmal ansehen) und dass du sinnigerweise beides in ein Statement verpackst.
»»Aber du hast wieder ein logisches Problem
Du holst dir alle ID aus der Tabelle, verkehrt herum sortiert beschränkt auf einen Datensatz. Damit löscht du nun alle bis auf einen.
Also das funktioniert mit dem code von oben so wie gewollt. Auch ein 2tes und 3tes mal.
Ich hol mir die höchste id.
$abfrage = "SELECT ID FROM links ORDER BY ID DESC LIMIT 1";
Dann setzt ich $del als die höchtste id -10. In dem Fall.
$del = $row->ID -10;
und lösch alles was kleier als $del is.
$loeschen = "DELETE FROM links WHERE ID < $del";
Aber wenn ich nen Denkfehler hab erklär ihn mir mal bitte einer. :)
Das mit Subquerys hab ich noch nie gemacht. Schau ich mir aber mal an.
Also das funktioniert mit dem code von oben so wie gewollt. Auch ein 2tes und 3tes mal.
Ja, solange du aufeinanderfolgende, nummerische Identifikationsmerkmale hast und niemals zwischen drinnen einen Datensatz aus anderen Gründen entfernst oder in der Nummernabfolge eine Lücke erzeugt wird. Wenn du z.B. die neueren Datensätze aufgrund eines Timestamps ermittelst (z.B. letzte Änderung), ist dein System bereits zum scheitern verurteilt.
Aber wenn ich nen Denkfehler hab erklär ihn mir mal bitte einer. :)
Der Denkfehler ist, dass du von der höchsten ID einfach 10 abziehst. Du müsstest entweder den Zeiger des Datenbankobjekts verschieben (ich weiss aber nicht, ob das überhaupt mit PHP/MySQL geht) oder eben gleich den zehnten Datensatz abfragen. Zudem bleiben dir so immer 11 Datensätze, nicht 10 :)
Angenommen du hast folgendes:
id | title
---+------
1 | foo
2 | foo
3 | foo
4 | foo
5 | foo
6 | foo
7 | foo
8 | foo
9 | foo
10 | foo
11 | foo
12 | foo
13 | foo
14 | foo
15 | foo
16 | foo
17 | foo
18 | foo
19 | foo
Jetzt erhältst du mit der ersten Abfrage "20" zurück, ziehst davon 10 ab und löscht alles < 9 - bis auf die 11- statt 10-Sache ist alles in Ordnung.
Jetzt mit dieser Tabelle
id | title
---+------
1 | foo
2 | foo
3 | foo
4 | foo
5 | foo
6 | foo
7 | foo
9 | foo
11 | foo
13 | foo
14 | foo
15 | foo
20 | foo
25 | foo
30 | foo
35 | foo
40 | foo
45 | foo
50 | foo
Du erhältst jetzt 50 zurück, ziehst davon 10 ab und löscht alles < 40 - somit bleiben dir nur noch 3 Datensätze übrig.
Genau aus dem Grund musst du dir den 10. _Datensatz_ von unten holen und alles < dem Ergebnis löschen. Im ersten Beispiel wäre das ID 10, im 2. Beispiel ist das ID 13.
Das mit Subquerys hab ich noch nie gemacht. Schau ich mir aber mal an.
Funktioniert in diesem Fall mit MySQL nicht, war eine Wissenslücke von mir :).
Genau aus dem Grund musst du dir den 10. _Datensatz_ von unten holen und alles < dem Ergebnis löschen. Im ersten Beispiel wäre das ID 10, im 2. Beispiel ist das ID 13.
Okay verstanden und Umgesetzt.
»» Das mit Subquerys hab ich noch nie gemacht. Schau ich mir aber mal an.
Funktioniert in diesem Fall mit MySQL nicht, war eine Wissenslücke von mir :).
Ok :)
Danke dir.
echo $begrüßung;
Du hantierst ja immer noch mit den ID rum. Diese erscheinen nur rein optisch als ein geeignetes Sortierkriterium. Du willst die x neuesten Datensätze, also sortiere nach einem Zeit-Kriterium. Wenn du dafür noch keine Spalte in der Tabelle hast, leg eine TIMESTAMP-Spalte an. TIMESTAMP hat einen eingebauten Mechanismus, der beim Erstellen und wenn gewünscht auch beim Update die aktuelle Zeit hinterlässt.
Da du nicht gleichzeitig selektieren und Daten ändern kannst, brauchst du eine Möglichkeit, die x Datensätze zuerst zu ermitteln und sie zwischenzuspeichern. Dazu bietet sich eine temporäre Tabelle an (wenn du die Berechtigung hast, eine solche anzulegen)
CREATE TEMPORARY TABLE temp
SELECT id FROM tabelle ORDER BY zeitspalte DESC LIMIT 30
Das legt eine Tabelle mit den ID der 30 neuesten Datensätze an. Temporäre Tabellen bleiben für die Dauer einer Sitzung erhalten und werden danach wieder entfernt. Nun kannst du die Daten löschen und dabei die in temp enthaltenen dabei ausschließen:
DELETE FROM tabelle
USING tabelle LEFT JOIN temp ON tabelle.id = temp.id
WHERE temp.id IS NULL
oder
DELETE FROM tabelle WHERE id NOT IN (SELECT id FROM temp)
echo "$verabschiedung $name";
echo $begrüßung;
Das kannst du bequem in ein DELETE-Statement mit Subselect verpacken.
Kann er nicht, denn mit MySQL kann man keine Datensätze ändern oder löschen, wenn man mit einem Subselect auf die selbe Tabelle zugreift.
echo "$verabschiedung $name";
Kann er nicht, denn mit MySQL kann man keine Datensätze ändern oder löschen, wenn man mit einem Subselect auf die selbe Tabelle zugreift.
Interessant zu wissen, hast du einen Link zur Hand, wo man diese (und ähnliche Einschränkungen) nachlesen kann?
echo $begrüßung;
» Kann er nicht, denn mit MySQL kann man keine Datensätze ändern oder löschen, wenn man mit einem Subselect auf die selbe Tabelle zugreift.
Interessant zu wissen, hast du einen Link zur Hand, wo man diese (und ähnliche Einschränkungen) nachlesen kann?
Na klar: http://dev.mysql.com/doc/refman/5.1/en/ ... den hätteste jetzt nicht erwartet. Genauer gesagt: SQL-Syntax -> Data Manipulation Syntax -> UPDATE bzw. DELETE
echo "$verabschiedung $name";
Na klar: http://dev.mysql.com/doc/refman/5.1/en/ ... den hätteste jetzt nicht erwartet. Genauer gesagt: SQL-Syntax -> Data Manipulation Syntax -> UPDATE bzw. DELETE
Gefunden:
"Currently, you cannot delete from a table and select from the same table in a subquery."
Es besteht also noch Hoffnung :)