• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Menüprogrammierung (PHP - Postgres-DB)

hallo leute,

vielleicht könnt ihr mir ja helfen.

ich programmiere gerade eine menüstruktur, welche in einer db gespeichert wird, sodass laien neue menüpunkte hinzufügen können.
damit man entscheiden kann, wo ein neuer punkt hinzugefügt wird, speichere ich das ranking des eintrags (nicht id, sondern extra-feld).

meine tabelle in der db sieht so aus

Code:
create table navigation(
  id serial not null primary key,
  designation varchar(30) not null,
  url varchar(100),
  sub integer not null,
  rank integer not null);

mein bisheriger code sieht so aus

Code:
$prank = $_POST['rank'];
$query = pg_query($conn, "SELECT rank FROM navigation ORDER BY rank");
  while($data = pg_fetch_object($query))
    {
	$rank = $data -> rank;
	if($rank >= $prank)
	 {
	    $newrank = $rank + 1;
	     pg_query($conn, "UPDATE navigation SET rank = '$newrank' WHERE rank = '$rank'");
          }
     }
					
$query = pg_query($conn, "INSERT INTO navigation (markup,url,target,rank,sub)
	VALUES(
		'$_POST[markup]',
		'$_POST[url]',
		'$_POST[target]',
		'$prank',
		'$_POST[sub]'
		)");
					
pg_close($conn);

mein problem besteht hier in der dynamik. wenn ich einen eintrag zwischendrin einfüge, müssen sich natürlich alle einträge darunter mitändern (im ranking). ich kriegs einfach nicht gebacken. mit dem obigen habe ich das problem, dass sich der eintrag zwar an der richtigen stelle einfügen lässt, allerdings die folgenden einträge alle den gleichen ranking-wert bekommen und der ranking-wert dem des letzten eintrags +1 entspricht.

weiss einer warum?
 
Lösung in purem SQL (wie Du das dann in PHP (? Dein Sourcecode sieht so aus) umsetzt, mußt Du halt schaun, ich würde es mit prepared statements machen):

BEGIN;
INSERT INTO navigation (designation ,url, sub,rank) VALUES ('$designation','$url',$sub,$rank);
UPDATE navigation SET rank=rank+1 WHERE (rank >= $rank) AND id < (SELECT max(id) FROM navigation);
COMMIT;

Fügst Du einen Eintrag mit gleichem rank hinzu, werden die ranks aller vorhandenen Einträge, deren rank >= dem des eingefügten ist, um 1 erhöht. $xxx enthält den jeweiligen Wert, naja, ich denke, Du siehst, wie ich das meine.

Diese Lösung hat einer Nicht-SQL-Lösung gegenüber den Vorteil, daß nicht zwei Leute gelichzeitig am gleichen Eintrag rumpfuschen und Chaos verursachen. Sowas sollte man IMMER in Transaktionen kapseln. Mit PostgreSQL hast Du da schon die richtige Datenbank gewählt. :D

Wofür ist das sub? Für submenü-Nummern? Dafür könntest Du die Query passend erweitern.
 
BEGIN;
INSERT INTO navigation (designation ,url, sub,rank) VALUES ('$designation','$url',$sub,$rank);
UPDATE navigation SET rank=rank+1 WHERE (rank >= $rank) AND id < (SELECT max(id) FROM navigation);
COMMIT;

funktioniert super..allerdings muss ich gestehen, dass ich nicht ganz verstehe, warum das nun funktioniert. letztendlich sieht das nicht viel anders aus wie in meinem php-code, aber ich verstehe den punkt

id < (SELECT max(id) FROM navigation);

nicht. was genau soll das bewirken?
 
thesecondjoker schrieb:
BEGIN;
INSERT INTO navigation (designation ,url, sub,rank) VALUES ('$designation','$url',$sub,$rank);
UPDATE navigation SET rank=rank+1 WHERE (rank >= $rank) AND id < (SELECT max(id) FROM navigation);
COMMIT;

funktioniert super..allerdings muss ich gestehen, dass ich nicht ganz verstehe, warum das nun funktioniert. letztendlich sieht das nicht viel anders aus wie in meinem php-code, aber ich verstehe den punkt

id < (SELECT max(id) FROM navigation);

nicht. was genau soll das bewirken?

Dein id ist ein serial, d.h. jeder neu INSERTete Wert bekommt eine id, die sicher höher ist als alle vorhandenen ids (es sei denn, du kriegst einen Überlauf, was bei einer int8 eine Weile dauern dürfte :D). Das wiederum heißt, daß alle vorhandenen Einträge eine id haben, die kleiner ist, als die des neuen Eintrags. Wenn Du also den rank aller Einträge, die älter (id kleiner als die des neuen Eintrags , welchletzterer (id = max(id) hat) sind als der neue und einen rank größer oder gleich dem des neuen haben, um eines erhöhst, dann paßt es. Genau das macht der UPDATE.

Kurz gesagt: id ist das Alter des Eintrags. Je niedriger die id, desto älter der Eintrag. Der neueste Eintrag hat die höchste id (max(id)).

Mit dem subselect muß das gemacht werden, weil aggregates (max() ist ein solcher) im WHERE nicht erlaubt sind. Sonst könnte man einfach
Code:
id < max(id)
schreiben.

Noch ein Tip: Wenn die die Alternative hast, etwas gleichwertiges entweder per Scriptzeilen oder direkt in der Datenbank zu machen, dann mach es in der Datenbank (und kapsele es, wenn mehr als eine Query involviert ist, unbedingt in einer Transaktion)! Die Vorteile sind:

1. Script ist lahm (interpretiert), Datenbank ist flott (kompiliert). Außerdem ists weniger und kompakterer Code.
2. Im Fehlerfall wirft die Datenbank detaillierte Fehlermeldungen. PHP ist da eher lausig und man sucht sich gelegentlich fast tot, wenn ein Datenbankfehler auftritt. Man weiß nämlich nie genau: War das jetzt mein PHP-Code oder meine Query?
3. Durch die Transaktion kann nicht passieren, daß zwei Leute gleichzeitig dasselbe mit anderen Werten machen, INSERT und UPDATE sind nach außen eine Operation.
 
thesecondjoker schrieb:
dachte bisher immer, dass man der db wenig arbeit machen sollte und lieber die arbeit vom programm erledigen zu lassen, damit die db perfomant bleibt, gerade bei vielen zugriffen!

Das gilt vielleicht für ne MySQL. :D

Die PostgreSQL ist schon gut für heftigen Beschuß geeignet, im Multiuserzugriff spielt sie ihre Stärken erst richtig aus und knickt so leicht nicht ein. Allerdings solltest Du sie in Produktion nicht in der Defaultkonfiguration belassen, schau mal bei www.postgresql.org nach den diversen "Tuningvorschlägen". Ein wenig drehen bringt bei einigen Optionen einen echten Performanceschub. Die Konfiguration ist im Auslieferzustand so, daß sie auf minimaler Hardware läuft.

Für intensive Ausnutzung der Datenbank spricht auch, daß etliche Beziehungen zwischen den Daten gleich in der Datenbank definiert werden können (zB "Der Auftrag darf nur dann angelegt werden, wenn der Kunde in der Kundentabelle schon vorhanden und nicht gesperrt ist" oder "Das Kaufdatum darf maximal 2 Jahre vor heute liegen"). Die mußt Du dann nicht mehr mühsam im Script abfangen, die Datenbank checkt Deine Daten und wirft einen passenden Fehler, wenn was nicht stimmt. Das erspart viel viel Arbeit beim Scriptprogrammieren!

Ich benutze PostgreSQL seit Jahren im Webserverbereich mit mehreren Webservern parallel, die auf einen gemeinsamen Datenbankserver zugreifen (Datenbank ca 2G groß, um die 20-30000 Queries pro Tag von 07:00 - 20:00) und habe bislang nie Performance- oder gar Zuverlässigkeitsprobleme gehabt, obwohl die Hardware nicht unbedingt die alleraktuellste ist.

:!:Benutze bei Webprojekten immer prepared statements, um SQL-Injektionen aus Input-Feldern zu verhindern:!:
 
danke für die infos...

hier aber noch ein paar fragen dazu:

1. was genau sind prepared statements ( - trigger?)?
2. wie lege ich die an?

und noch andere (wenn ich schonmal nen postgres-prof. an der hand hab :D ):

3. wie mache ich am sinnvollsten ein update des dbms, wenn z.b. eine neue version heruaskommt?
4. welche einstellungen sollte ich aus perfomancegründen ändern?


sorry für die fragen. ich weiss, ich könnte das auch aus dem internet suchen, nur leider ist das meistens etwas kompliziert erkärt und ich arbeite produktiv erst seit ca. 6 monaten mit php und psql. außerdem bin ich auch noch kein unheimlicher sql- bzw. db-prof. (aber ich weiss das ms access keine db bzw. dbms ist! :D )
 
thesecondjoker schrieb:
danke für die infos...

hier aber noch ein paar fragen dazu:

1. was genau sind prepared statements ( - trigger?)?
2. wie lege ich die an?

und noch andere (wenn ich schonmal nen postgres-prof. an der hand hab :D ):

3. wie mache ich am sinnvollsten ein update des dbms, wenn z.b. eine neue version heruaskommt?
4. welche einstellungen sollte ich aus perfomancegründen ändern?


sorry für die fragen. ich weiss, ich könnte das auch aus dem internet suchen, nur leider ist das meistens etwas kompliziert erkärt und ich arbeite produktiv erst seit ca. 6 monaten mit php und psql. außerdem bin ich auch noch kein unheimlicher sql- bzw. db-prof. (aber ich weiss das ms access keine db bzw. dbms ist! :D )

STOP!


schau dir deinen Topic an ... und nun geht es um Datenbank-Optimierungen ..
bitte eröffne einen neuen Thread! Ansonsten werde ich alles was nicht mit der Menuprogrammierung zu tun hat gen /dev/null schieben ..

Etwas Ordung und Disziplin sollte schon gewahrt bleiben !

und das mit der Gross-/Kleinschreibung. Versuche es wenigstens. Die nicht zum Thema gehörenden Beiträge sind gerade nach /dev/null verschwunden :)
 
Oben