PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Datenbankeinträge auf Zeit


nightflasher
15.08.2003, 10:30:32
Hi,

weiss jemand, ob es möglich ist, Datenbankeinträge auf Zeit in
eine MySQL-Database zu schreiben.

Erklärung:

Ich habe DB-Einträge, die ich mit einer Timestamp versehe und in
eine DB schreibe. Diese sollen dann zum angegebenen Zeitpunkt automatisch gelöscht werden.

Bisher löse ich dies noch manuell.
Geht auch sehr gut, da aber andere Datenbanken diese Funktion
teilweise unterstützen wollte ich mich mal informieren.

Gruß,
Helge

Nev
15.08.2003, 18:51:18
Hi nightflasher

In Mysql selbst gibt es so eine Möglichkeit ned.

Du kannst dir nur ein kleines Prog schreiben zB. PHP /PERL
das dir die Einträge löscht.

Aufgerufen wird es mittels eines Cron-Job.


Wenn ich so weiter denke, wird es wahrscheinlich so sein, das hierbei viele Datensätze gelöscht werden, oder??

Daher solltest du auch den Table Optimieren!
-> OPTIMIZE TABLE `TABLENAME`

Jürg
16.08.2003, 14:30:48
Vielleich hilft folgendes Script.
Wird in die Seiten im "oberen" Teil mit include eingebunden und durchlaufen vor die Anzeige erfolgt. Das geht sehr schnell.
Beachte, das Script löscht auch Einträge aus einem Verzeichnis.

<!-- upload-datum.txt loescht Eintragungen die verfallen sind -->
<?php
include ("../open.inc.php");
// aus open.inc.php kommt $conn
// herausfinden ob Dateien verfallen sind
$query = "select * FROM XXXXXX_upload ";
$result = mysql_query($query,$conn);
$num = mysql_numrows($result);
for ($i = 0; $i < $num; $i++){
$row = mysql_fetch_array($result);
$heute = date("Ymd");
$Aktive = $row[Aktive];
$VBZ = $row[VBZ];
$Presse = $row[Presse];
$Spezial = $row[Spezial];
// herausfinden ob Dateinen verfallen sind
$id = $row[id];
$Datei = $row[Datei];
$Verfall = $row[Verfall];
$vtag = substr($Verfall,8,2);
$vmonat = substr($Verfall,5,2);
$vjahr = substr($Verfall,0,4);
$verfall1 = $vjahr * 10000 + $vmonat *100 + $vtag;
//ist ein Verfalldatum vorhanden
if ($Verfall == "0000-00-00") {
$x = "druck";}
else {
if ($verfall1 > $heute) {
$x = "druck";}
else {$x = "loesch";}
};
// Dateien allenfalls löschen
if ($x == "loesch") {
//Datei in Verzeichnis löschen
if ($Aktive == "" && $VBZ == "" && $Presse == "" && $Spezial =="")
{ $dateiname = "Upload/";}
else
{ $dateiname = "../Upload/";}
$Datei = mysql_result($result,$i,"Datei");
$url = $dateiname;
$url .= $Datei;
unlink($url);
//Datei in DB löschen
$query = "DELETE FROM XXXXXX_upload where id = '$id'";
mysql_query($query);
}
}
?>

MiH
18.08.2003, 09:24:33
ist nicht ein

delete from TABLE where timestamp < unix_timestamp(now());

einfacher? :)

Dommy
19.07.2004, 23:30:07
Heißt das, dass ich so alle Einträge in meiner Tabelle tracker löschen kann, die älter sind als 5 Minuten ?


$time = date(YmdHis);
$timelog = ($time-500);

$sqldumb = ("DELETE * FROM TABLE tracker WHERE date < '$timelog'");
$result_dumb = mysql_query($sqldumb);


wobei die Tabelle tracker folgende Spalten enthält:

ip => INT(12)
date => TIMESTAMP(14)

c4
20.07.2004, 09:12:21
Da hast Du aber einige Verständnisfehler eingebaut...

Keine Ahnung, ob das klappt: $sqldumb = "DELETE *
FROM tracker
WHERE date < DATE_SUB(date, INTERVAL 5 MINUTES)";

$result_dumb = mysql_query($sqldumb);

- 5 Minuten = 300 Sekunden, nicht 500
- die Rechnung ergibt keinen Sinn
- Zeichenketten in ' oder " (date('YmdHis'))
- Feldtyp TIMESTAMP hat nichts mit YmdHis zu tun
- 'date' als Feldname ist ungünstig, da 'date' ein reserviertes Wort ist
- Zuweisung von Strings zu Variable kann ohne Klammer, da keine Funktion

Dommy
20.07.2004, 12:17:16
Erklärung der 500:

Das Feld date in der Tabelle ist ja ein TIMESTAMP (14), also eine 14-stellige Zahl.
Sobal eine Minute vorbei ist wird doch die 3letzte Zahl um eins erhöht (zB. 20040719112259 wird in der nächsten Sekunde zu 20040719112300). Deshalb der Grundgedanke mit den 500 für 5 Minuten.

Aber das ist bestimmt etwas zu umständlich gedacht!

$time = (date("YmdHis")); //zuerst die aktuelle Zeit im Timestamp-Format (14stellig)
$timelog = ($time-500); // nun 5 Minuten abziehen. Weshalb 500 siehe oben
$sqldumb = ("DELETE * FROM TABLE tracker WHERE zeitpunkt < '$timelog'"); //ok, aus date mach zeitpunkt
$result_dumb = mysql_query($sqldumb);

//wobei die Tabelle tracker folgende Spalten enthält:

ip => INT(12)
zeitpunkt => TIMESTAMP(14)



Hoffe mein Grundgedanke ist jetzt deutlicher zu erkennen!
Ich werde aber auch mal Deinen Vorschlag testen! Wäre aber gut wenn sich jemand nochmal meine Idee zu Gemüte führen würde!

c4
20.07.2004, 12:23:29
Hast Du mein Skript eigentlich mal probiert?
Du hast ja noch so einigen Unsinn drin, von dem ich Dir abgeraten habe!

Das mit der 500 ist nicht ganz zu Ende gedacht. Beispiel:
20040719110259 - 500 = 20040719109759
Problem erkannt?

Also nimm DATE_DIFF() oder DATE_ADD() oder DATE_SUB()
--> http://dev.mysql.com/doc/mysql/de/Date_and_time_functions.html

Dommy
20.07.2004, 13:25:54
Stimmt, das hatte ich nicht bedacht!
Aber wie bereits erwähnt werde ich deinen Vorschlag testen sobald ich Zeit habe!

Dommy
21.07.2004, 00:09:17
So habe mal Deinen Vorschlag berücksichtigt und nun sieht das Script so aus:

$db=mysql_connect($server,$user,$password); // Aufbau einer Verbindung zum Datenbankserver
mysql_select_db($database); // Datenbank auswählen
$ip = $_SERVER['REMOTE_ADDR'];
$ipclean = str_replace(".","",$ip);

$sqldumb = "DELETE * FROM tracker WHERE zeitpunkt < DATE_SUB(date, INTERVAL 5 MINUTES)";
$result_dumb = mysql_query($sqldumb);

$sql = "SELECT * FROM tracker WHERE 1 AND ip = '$ipclean'";
$anfrage = mysql_query($sql) OR die(mysql_error());
if (!mysql_num_rows($anfrage))
{
$sql_insert = "INSERT INTO tracker (ip,zeitpunkt) VALUES ('$ipclean',NOW())";
$anfrage_insert = mysql_query($sql_insert);
$sql_count = "SELECT * FROM counter";
$anfrage_count = mysql_query($sql_count);
$row = mysql_fetch_array($anfrage_count, MYSQL_ASSOC);
$hits = $row['hits'];
$hits_new = ($hits+1);
$sql_count = "UPDATE counter SET hits = '$hits_new'";
$anfrage_count = mysql_query($sql_count);
} else {
$sql_update = "UPDATE tracker SET zeitpunkt = NOW() WHERE ip = '$ipclean'";
$anfrage_update = mysql_query($sql_update);
}
mysql_close($db);


Das komische ist nur, dass obwohl die IP schon in der Tab drinnen steht er trotzdem wieder eine neue Zeile einfügt (mit der gleichen IP) .
Ich glaube das liegt wohl an if (!mysql_num_rows($anfrage)) aber ich sehe den Fehler net.
Kann mir bitte jemand helfen?

Dabei möchte ich noch anmerken, dass das Script auf meinem lokalen WebServer einwandfrei läuft und es da dieses Problem nicht gibt!

c4
21.07.2004, 09:14:56
Was soll er denn auch ausgeben? Wenn keine Fehler auftreten, gibt's für ihn auch nichts zu sagen.

Ich habe Dir das mal ein wenig angepasst: $db=mysql_connect($server, $user, $password);
mysql_select_db($database);

$ip = $_SERVER['REMOTE_ADDR'];
// Du könntest die IP auch in einem CHAR(15) speichern, damit ersparst Du Dir diesen Quatsch
$ipclean = str_replace('.', '', $ip);

// Es ist nicht notwendig einmalig verwendete Abfrage extra in einer Variable zu speichern
// Auch das Ergebnis der Abfrage wird meist nicht benötigt
mysql_query('DELETE * FROM tracker WHERE zeitpunkt < DATE_SUB(date, INTERVAL 5 MINUTES)') or die(mysql_error());

// Zahlen schreibt man nicht in Hochkommas!!
// WHERE 1 ist auch überflüssig
$anfrage = mysql_query("SELECT * FROM tracker WHERE ip=$ipclean") or die(mysql_error());

// Mag sein, dass das mit dem ! klappt, aber mach lieber einen Mengenvergleich
if (mysql_num_rows($anfrage)<=0) {
mysql_query("INSERT INTO tracker (ip, zeitpunkt) VALUES ($ipclean, NOW())") or die(mysql_error());

// Du musst nicht erst den alten Wert auslesen, Du kannst ihn auch gleich inkrementieren
mysql_query('UPDATE counter SET hits=hits+1') or die(mysql_error());

// Das Auslesen kannst Du so übrigens eleganter machen:
// $result=mysql_query('SELECT hits FROM counter');
// list($hits)=mysql_fetch_row($result);
// Danach steht Dir der Wert von hits in $hits zur Verfügung
}
else {
mysql_query("UPDATE tracker SET zeitpunkt=NOW() WHERE ip=$ipclean");
}

mysql_close($db); Das or die(mysql_error()) hat in einem fertigen Skript nichts mehr zu suchen. Entferne es also, wenn Du das Ding online stellst!


Ach ja: Welche PHP-Version hast Du lokal, bzw. online am laufen?

Dommy
21.07.2004, 13:09:12
lokale Version:
PHP Version 4.3.6
Apache/2.0.50 (Fedora)
MySQL 3.23.58 API Version

online Version:
Apache/1.3.27 (Linux/SuSE) mod_jk/1.2.2-dev mod_ssl/2.8.12 OpenSSL/0.9.6i PHP/4.3.4 mod_perl/1.27 FrontPage/4.0.4.3
MySQL 3.23.55


Mir ist bewusst, dass es nicht gerade gut ist auf 2 verschiedenen Server-Umgebungen zu programmieren, aber ich wollte eigentlich eine serverunabhängige Site haben weil ich ja net weiss wie lange ich ncoh bei dem Anbieter bleibe zumal der Server schon ein paar Mal eingebrochen ist , aber egal!


Zum eigentlichen Problem:
lokal sieht die Sache gut aus und er füht auch nicht unnötig neue Zeilen ein, aber es werden auch nicht die zu alten Einträge gelöscht, also gehe ich davon aus, dass an folgendem Befehl etwas nicht korrekt abläuft
mysql_query("DELETE * FROM tracker WHERE zeitpunkt < DATE_SUB(date, INTERVAL 5 MINUTES)");


Online sieht die Sache allerdings schon ganz anders und das ist ja auch das Problem.
Erstens werden wie bei der lokalen Variante auch die zu alten Einträge nicht gelöscht (ich spare mir das Posten der Zeile)
Zweitens wird obwohl die IP gleich bleibt jedes Mal eine neue Zeile angelegt! Also wird wohl etwas an diesem Befehl vom Server net richtig verarbeitet würde ich sagen

if (mysql_num_rows($anfrage)<=0) {
mysql_query("INSERT INTO tracker (ip, zeitpunkt) VALUES ($ipclean, NOW())");
mysql_query('UPDATE counter SET hits=hits+1');
} else {
mysql_query("UPDATE tracker SET zeitpunkt=NOW() WHERE ip=$ipclean");
}


An der if-Abfrage scheint es wohl ein Problem zu geben, da jedes Mal der erste teil durchlaufen wird und nicht falls von Nöten der Else-Teil! Liegt das an den unterschiedlichen PHP-Versionen ?

Trotzdem schon einmal großen Dank für Deine Hilfe! Wäre super wenn das Problem auch noch gelößt werden könnte!

c4
21.07.2004, 13:19:50
Das nenne ich doch mal eine Fehlerbeschreibung!

Du hast mein Skript aber nicht komplett übernommen, richtig? Meine mysql_error() scheinen zu fehlen.

Die Abfrage mysql_query("DELETE * FROM tracker WHERE zeitpunkt < DATE_SUB(date, INTERVAL 5 MINUTES)"); arbeitet noch mit dem Feldnamen date, das muss natürlich auch zeitpunkt heißen: mysql_query("DELETE * FROM tracker WHERE zeitpunkt < DATE_SUB(zeitpunkt, INTERVAL 5 MINUTES)");

An den genutzten System liegt das Problem nicht.

Dommy
21.07.2004, 14:31:10
Wieso? War die Fehlerbeschreibung net deutlich?

Habe jetzt Deine OR die(mysql_error()); auch noch drangehängt und jetzt halte fest:
Es gibt Probleme mit dem Befehl
mysql_query("DELETE * FROM tracker WHERE zeitpunkt < DATE_SUB(zeitpunkt, INTERVAL 5 MINUTES)") OR die(mysql_error());

und zwar:
You have an error in your SQL syntax near '* FROM tracker WHERE zeitpunkt < DATE_SUB(zeitpunkt, INTERVAL 5 MINUTE)' at line 1

Ich habe das MINUTES durch MINUTE ersetzt weil ich es auf der Site http://dev.mysql.com/doc/mysql/de/Date_and_time_functions.html
verstanden habe, aber auch mit MINUTES kommt der Fehler !
Liegt das Problem daran, dass das Feld zeitpunkt vom Typ TIMESTAMP(14) ist und nicht ein DATE oder DATETIME ?

c4
21.07.2004, 14:33:23
War die Fehlerbeschreibung net deutlich? Oh doch! Liegt das Problem daran, dass das Feld zeitpunkt vom Typ TIMESTAMP(14) ist und nicht ein DATE oder DATETIME ? Gut möglich, probier's aus!

Dommy
21.07.2004, 15:15:04
OK! zeitpunkt ist nun vom TYP DATETIME aber gleiches Resultat!
Daraufhin habe ich nun den Befehl folgendermaßen geändert
mysql_query("DELETE * FROM tracker WHERE zeitpunkt < DATE_SUB('zeitpunkt', INTERVAL '-0 0:5' DAY_MINUTE)") OR die(mysql_error());

aber immer noch diese Fehlermeldung!

Dommy
21.07.2004, 19:48:42
Folgendermaßen funktioniert das Script ganz gut, zumindest die Löschung aller Einträge, die älter als 5 Minuten sind, aber ist das auch die optimale Schreibweise?

$delete = mysql_query("DELETE FROM tracker WHERE zeitpunkt < DATE_SUB(NOW(), INTERVAL '0 0:5:0' DAY_SECOND)") OR die(mysql_error());
if ($delete)
{
mysql_query("OPTIMIZE TABLE `tracker`");
}


Leider ist das Problem mit dem updaten bereits vorhandener IPs noch nicht behoben!

c4
22.07.2004, 09:34:27
Die Idee mit dem NOW() statt zeitpunkt habe ich wohl glatt übersehen...

Kannst es ja wieder mit dem '5 MINUTES' probieren. Ansonsten passt das so schon.

Dommy
22.07.2004, 12:49:00
Kein Problem, hast mir trotzdem sehr geholfen!
HAbe mich dann erstmal durch die Online Doku von MySQL durchgelesen (zumindest diesen Abschnitt)!
Aber eine Frage habe ich noch:
Heisst das jetzt INTERVAL 5 MINUTES oder INTERVAL 5 MINUTE weil ich in der Beschreibung nur letzteres gefunden habe!

c4
22.07.2004, 12:56:37
Dann nimm letzteres.

Die Wahrscheinlichkeit, dass ich etwas sage, was im Manual anders steht und ich auch noch Recht habe damit ist doch recht gering... ;)