| 

.NET C# Java Javascript Exception

1
Die Hitze setzt mir zu und vernebelt meine MySQL-Kentnisse.

Ich habe folgendes vor:

1. Tabelle mit Daten (id, name, content, kategorie_id, datum (als unix timestamp) usw..) nennen wir sie mal tabelle_1

2. Tabelle mit Kategorien (id, name, ttl (in Tagen)) hier tabelle_2

ttl ist das maximale Alter der Detaildatensätze aus tabelle_1 für die jeweilige Kategorie.
Ich möchte nun per Cronjob die Datensätze aus tabelle_1 löschen wenn deren Alter den Wert ttl in tabelle_2 überschritten hat.

Ich habe es mit folgendem Statement versucht:

DELETE FROM tabelle_1 WHERE id IN (
SELECT t1.id
FROM tabelle_1 t1
LEFT JOIN tabelle_2 t2 ON t1.kategorie_id = t2.id
WHERE (
UNIX_TIMESTAMP( ) - t1.datum
) > ( t2.ttl * 86400 )
)


Das ganze wird mir quittiert mit:

#1093 - Die Verwendung der zu aktualisierenden Zieltabelle 'tabelle_1' ist in der FROM-Klausel nicht zulässig.



Jemand ne Idee ?
News:
16.07.2010
MiW 1,0k 1 8
3 Antworten
2
Du darfst in einem 'inner select' nicht die Tabelle verwenden aus der Du löschen willst.
Das geht einfach nicht ;)

Versuch mal so (ungetestet):
DELETE FROM tabelle_1 t1 WHERE 
UNIX_TIMESTAMP()-t1.datum > (SELECT ttl FROM tabelle2 WHERE id=t1.kategorie_id) * 86400


Ansonsten musst Du zweistufig arbeiten:
1) Alle (kat_id,TTL) Paare holen
2) Für alle Paare aus tab1 löschen (ein grosses query basteln oder einzelne queries)

[edit]
Geht übrigens übersichtlicher (wenn datum vom Typ DateTime ist):
datum < NOW() - INTERVAL ttl DAY
[/edit]
19.07.2010
DaSpors 4,2k 2 8
DaSpors 4,2k 2 8
1
vielen Dank für dein posting, das so leider nicht ganz funktioniert, weil MySQL mit dem t1 syntaktisch nichts anfangen kann.

in etwas abgewandeleter from erledigt es jedoch seine aufgabe bestens.

Das korrekte Statement lautet:

DELETE FROM tabelle_1 WHERE
(UNIX_TIMESTAMP() - tabelle1.datum) > ((SELECT t2.ttl FROM tabelle2 t2 WHERE t2.id=tabelle1.kategorie_id) * 86400)

MiW 26.07.2010
0
Oder du arbeitest eine Stored Procedure aus der du die Daten übergibst. Natürlich inkl. Rollback möglichkeit.

Beispiel aus unserer Produktion:
create procedure item_update(IN id INT(20), IN name VARCHAR(50), IN price float(10,2), OUT ret TINYINT)
begin
declare exit handler for not found rollback;
declare exit handler for sqlwarning rollback;
declare exit handler for sqlexception rollback;

set ret=0;
start transaction

-- insert into ...
-- update ...
-- any other DDL operation

commit;

set ret = 1;
end


was du der Funktion übergeben willst ist dir überlassen, vorteil ist das man sich im Code gar nicht mehr um die Selects kümmern muss und trotzdem sicher bleibt.

So Long
Spelter
24.07.2010
Stored Procedure schön und gut, aber das löst immer noch nicht das Katze-Schwanz-Problem des Delete-Statements...
FalkP 24.07.2010
So wie er allerdings seinen Tabellen Aufbau beschreibt sehe ich nicht wie er das lösen kann, denn das liest sich wie:

Tabelle 1 -> Items der WaWi: ID (des Items), Name, Kat_id, Datum des Hinzufügens
Tabelle 2 -> Kategorien: ID (von der Kategorie), Namen,Datum wann das letzte Item hinzugefügt wurde

Ein Item sollte eigentlich nur einmal in einer Kategorie sein. Möchte ich mehrere Kategorien, darf ich nicht von der Kategorie auf das Item referenzieren weil eine n:m beziehung besteht. Ich würde nur auf das Item Alter gehen und die Kategorie nur als Info verwenden.
Spelter 26.07.2010
"Datum wann das letzte Item hinzugefügt wurde" -> Nope, dort steht die TLL der Items
DaSpors 26.07.2010
Danke für dein Posting, aber ne stored procedure ist nicht ganz unproblematisch, da ich die Datenbank mit einer selbsgebauten PHP-DB-Klasse anspreche, die arge Probleme mit stored-procedures hat.
(SP erscheint mir für diese simple Aufgabe auch etwas übertrieben).

Das Statement von DaSpors funktioniert nach der oben genannten Korrektur bestens.
MiW 26.07.2010
0
Noch eine Möglichkeit:
Erweitere Tabelle1 um ein Feld valid_until und schreibe dort beim Erstellen des Items oder beim Einordnen in eine Kategorie einen Kategorie.TTL abhängigen Wert rein.
Oder mach es für alle:
UPDATE tab1 t1 SET t1.valid_until = t1.created + INTERVAL (SELECT ttl FROM tab2 t2 WHERE t2.id=t1.kat_id) DAY

Dann ist ein Löschen denkbar einfach:
DELETE FROM tab1 WHERE valid_until<NOW()
26.07.2010
DaSpors 4,2k 2 8
Ich nehme lieber die obere Lösung - Danke ;)
MiW 26.07.2010

Stelle deine Sql-Frage jetzt!