Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Baumstruktur kopieren (MySQL/PHP) (https://www.delphipraxis.net/174868-baumstruktur-kopieren-mysql-php.html)

fillibuster 15. Mai 2013 11:18

Baumstruktur kopieren (MySQL/PHP)
 
Hallo,

ich würde gerne eine Baumstruktur (Adjacency List Model) kopieren. Mein Problem sind die autoinc id Werte, die natürlich beim kopieren erneuert werden - folglich müssen auch die gesetzten parent_id's geändert werden. Hat da jemand einen Ansatz für mich? Gerne würde ich eine SQL Funktion nutzen, aber rekursiv fällt da schonmal flach. Meine Tabelle sieht so aus (obwohl Position nicht wichtig ist):

id|parent_id|position
1|0|1
2|1|1
3|1|2
4|0|2
5|4|1

RWarnecke 15. Mai 2013 12:46

AW: Baumstruktur kopieren (MySQL/PHP)
 
Wieso willst Du Dir die Arbeit machen und die ParentID's neu setzen ? Ich würde den Baum 1:1 kopieren und das AutoInc für den Kopiervorgang ausschalten. Nachdem Kopiervorgang den AutoInc-Wert der neuen Tabelle auf den höchsten Wert setzen.

Codehunter 15. Mai 2013 13:03

AW: Baumstruktur kopieren (MySQL/PHP)
 
So ganz verstehe ich das Problem noch nicht. Soll da eine ganze Tabelle dupliziert werden? Oder ist die Datenmenge das Ergebnis eines Views?

Bei MySQL z.B. kann man ja durchaus das Autoinc-Feld per Update und Insert beschreiben. Man muss nur aufpassen, dass das Feld kein Unique-Index ist, sonst raucht es u.U. mit einem Duplicate Entry Error.

sx2008 15. Mai 2013 13:33

AW: Baumstruktur kopieren (MySQL/PHP)
 
Zitat:

Zitat von RWarnecke (Beitrag 1215419)
Ich würde den Baum 1:1 kopieren und das AutoInc für den Kopiervorgang ausschalten.

So einfach ist das nicht.
Ausser der id muss auch bei jedem Datensatz die parent_id geändert werden.

Ich würde die Aufgabe mit Delphi in einer rekursiven Funktion lösen.
Delphi-Quellcode:
// kopiert einen Datensatz mit einer best. id und liefert die neue id zurück
function CopySingleNode(id, new_parent_id:integer):integer;

// liefert eine Liste mit alle Kindern zu einer bestimmten parent_id
procedure GetChildrenList(parent_id:integer; list:TIntegerList);

// kopiert rekursiv einen ganzen Zweig und hängt ihn unter parent_id ein
procedure CopyTree(id, parent_id:integer);
begin
  parent_id := CopySingleNode(id, parent_id);
  GetChildrenList(id, list);

  foreach x in list do
    CopyTree(x, parent_id); // rekursiver Aufruf
end;

fillibuster 15. Mai 2013 19:56

AW: Baumstruktur kopieren (MySQL/PHP)
 
Hi,

danke erstmal für eure Antworten. Wie sx2008 bemerkte reicht es nicht, alles einfach 1:1 zu kopieren - eben wegen der Abhängigkeit der parent_id's. Wie ich das in Delphi löse ist mir eigentlich klar, aber ich habe kein Delphi. MySQL kann keine Rekursiven Funktionen/Prozeduren mit beliebiger Rekursionstiefe :? und für PHP habe ich keinen wirklichen Ansatz (Array, ...?).

Hilfe

RWarnecke 15. Mai 2013 21:30

AW: Baumstruktur kopieren (MySQL/PHP)
 
Kopierst Du in eine neue Tabelle oder in eine bestehende Tabelle ? Wenn Du in eine neue Tabelle kopierst, kannst Du den folgenden Link benutzen. Ansonsten kannst Du das gleiche was sx2008 in Delphi geschrieben hat auch mit PHP umsetzen.

Edit: Link korrigiert

fillibuster 15. Mai 2013 21:34

AW: Baumstruktur kopieren (MySQL/PHP)
 
Hallo Rolf,

kopieren muss ich in eine neue Tabelle. Leider funktioniert dein Link nicht.

//Edit: Der Doppelpunkt war's ;-)
//Edit 2: Die Werte in Tabelle 2 also in die der Baum kopiert können sich später noch ändern (es werden Items hinzugefügt). Ich muss also neue id's/parent_id's generieren
//Edit 3: Muss dann wohl mit PHP sein ...

Medium 16. Mai 2013 00:42

AW: Baumstruktur kopieren (MySQL/PHP)
 
Ich hatte vor ein paar Jahren ein sehr ähnliches Problem. Der (nicht unwesentliche) Unterschied: Ich musste den "Baum" innerhalb der selben Tabelle duplizieren, so dass der Primärindex auf keinen Fall übernommen werden konnte.
Ich habe recht lange nach einer eleganten Lösung gesucht, die möglichst innerhalb von SQL besteht, leider auch ohne Erfolg. Letztlich habe ich es dann eben auch ausprogrammiert (allerdings in Delphi), und jedes Insert fein säuberlich von Hand gebaut. Besonders fies dabei ist ja: Man kann die Parent-IDs erst dann in der Kopie neu setzen, wenn die Kopie bereits besteht - vorher sind die Auto-Werte ja unbekannt. Daher wird jedes Insert noch mit einem Select und einem Update garniert, und man muss sich Gedanken darüber machen, wie man die ursprünglichen Abhängigkeiten effizient so puffert, dass sich die Parent-IDs nach dem Einfügen aller Knoten/Sätze noch sauber nachvollziehen lassen. (Besonders hübsch bei Graphen.) Bei ein paar zig Datensätzen ist das verschmerzbar, darüber wird es aber dann doch vergleichsweise langsam.

Da du aber in eine frische und daher vermutlich leere Tabelle kopieren willst, könnte sich das doch deutlich vereinfachen. Vor allem, wenn es eine nicht allzu oft durchgeführte Operation ist (seltener als alle paar zig Minuten): Einfach den Autoinc für die neue ID-Spalte aus machen, den Index darauf droppen, ganz naiv kopieren, und nachher Index und Autoinc wieder an schalten. Eventuell lässt sich das droppen des Index sogar noch vermeiden, jedoch weiss ich nicht ob das praktisch so wirklich klappt: Wenn man die Inserts innerhalb ein und der selben Transaktion durchführt, sollte sich das DMBS nicht über ungültige Zwischen-States beklagen. Eventuell! Wenn das geht, würde es auch für eine oft gemachte Routine taugen.

Wenn die neue Tabelle erst mit Anlegen der Kopie überhaupt erst erstellt wird, ließe sich daraus auch mit einem einigermaßen effizienten SQL Script was machen. Quasi:
SQL-Code:
CREATE TABLE foo ... // kein autoinc und index setzen!
INSERT INTO foo (id, bar, ...) VALUES (id1, blub), (id2, blub), ...
ALTER TABLE foo ... // autoinc setzen und index erzeugen
Mal so als lose Ideensammlung, die unverschämt ungetestet ist :)


(Randnotiz: Der DP SQL Highlighter mag "//" nicht als Kommentar-Token. Ist das non-standard?)

BUG 16. Mai 2013 00:59

AW: Baumstruktur kopieren (MySQL/PHP)
 
Zitat:

Zitat von Medium (Beitrag 1215464)
(Randnotiz: Der DP SQL Highlighter mag "//" nicht als Kommentar-Token. Ist das non-standard?)

Das sollte gehen:
SQL-Code:
CREATE TABLE foo ... -- kein autoinc und index setzen!
INSERT INTO foo (id, bar, ...) VALUES (id1, blub), (id2, blub), ...
ALTER TABLE foo ... -- autoinc setzen und index erzeugen
"//" als Zeilenkommentar hab ich in SQL noch nie gesehen :gruebel:

fillibuster 17. Mai 2013 12:20

AW: Baumstruktur kopieren (MySQL/PHP)
 
Hi,

noch eine Überlegung: ich schreibe eine Prozedur in SQL, die mir die aktuelle Baumstrunktur in eine temporäre Tabelle speichert. Diese enthält zwei zusätzliche Felder (new_id und new_parent_id). Dann erzeuge ich zuerst alle Datensätze neu, speichere die neuen id's in der temporären Tabelle und mache dann ein Update über die verschiedenen parent_id's. Was meint ihr?


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:00 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz