[Apache, phpmyadmin, html, PHP, ...] Datenbank mit webbasiertem Zugriff erstellen

  • Ersteller Ersteller boss3D
  • Erstellt am Erstellt am
isset($dauer) ist IMMER true, da es in der Zeile davor gesetzt wird.
Du meinst vermutlich isset($_POST[$ts])

EDIT: Google mal nach "ON DUPLICATE KEY UPDATE". Könnte dir weiterhelfen. Brauchst dann natürlich noch einen entsprechenden Index, aber das sollte das geringste Problem sein.

Hier wird das ausführlich erklärt - etwas einfacher zu lesen, als das offizielle SQL-Handbuch:
http://www.phpundmysql.de/2012/03/28/upsert-in-mysql-insert-on-duplicate-key-update/
 
Zuletzt bearbeitet:
ui, sowas hab ich immer gesucht (wenns das is, was ich denke). weil diese "doppelte" db anfrage hat mich scho immer genervt ><
 
Ja, weil ich nicht weiß, WIE ich die DB fragen soll. Ich kann ja nicht in ein query ein isset reinbauen um zu schauen, ob ein Feld in einer Zeile einen Wert hat. Bzw. es haben ja immer ALLE Felder in unserer DB einen Wert (bestenfalls Beschreibung kann leer bleiben, sonst aber nichts) ...

BTW: Ob DB-fragen, oder Website-Felder mit isset auf Inhalt abfragen, läuft doch aufs selbe hinaus?! Wenn ein Feld einen Inhalt hatte, dann muss genau dafür auch was in der DB stehen, ergo weiß ich --> UPDATE. Hatte ein Feld keinen Inhalt (isset()=false), kann auch nichts in der DB stehen, ergo --> INSERT.
Wieso also sollte mein Ansatz, den ich verstehen würde, nicht funktionieren? Warum die DB fragen?
 
Zuletzt bearbeitet:
na die "naive" lösung ist doch ganz simpel >< frag per select (das hab ich dir in meinem pseudocode ablauf da sogar schon ausformuliert) nach dem datensatz. wenn die db ein ergebnis liefert, gibt es so einen datensatz schon. ist das ergebnis leer, gibts den nicht.


zu dem on update... das scheints nur für key zu geben? für eine beliebige spalte wäre es mMn sinnvoller. weil mit key können wir leider nix anfangen (wenn ich das richtig verstanden hab). einerseits wäre in der projekte-tabelle die prID zwar ein unique key, aber eben auch auto-increment. somit fiele das schonmal raus. erschwerend kommt hinzu, dass wir NICHT in projekte nach der id glotzen, sondern in zeiten. und dort ist die "referenz" prID (man würde normalerweise foreign key sagen, aber an sowas stört sich mysql glaube nich :/ ) eben kein key element. schon garnich unique. man müsste also irgendwie sowas bauen können:
insert into zeiten... MOMENT! ginge es vllt so?

INSERT INTO zeiten (zeit) VALUES ($datum) WHERE prID='$prID' AND datum='$ts' AND user='$userid' AND NOT SELECT * FROM zeiten WHERE prID='$prID' AND datum='$ts' AND user='$userid';
wenn ichs jetzt richtig interpretiere, würde er dann nur insert machen, wenn der datensatz nich schon existiert oder? aber gut, was hätte man gewonnen? das selbe müsste man nochmal für update machen (ohne not diesmal) und ggf für delete (wobei das in nem anderen if-zweig wäre). wir hätten aber dennoch wieder 2 anfragen *grübel*

mist ^^


edit: ich glaube die abfrage, die ich eben meinte, müsste so lauten:
INSERT INTO zeiten (zeit) VALUES ($datum) WHERE prID='$prID' AND datum='$ts' AND user='$userid' AND SELECT count(id) FROM zeiten WHERE prID='$prID' AND datum='$ts' AND user='$userid' = '0';



edit2: oha, das nennt man wohl nested queries (wenns wen interessiert) und man sollte wohl ne klammer drum bauen ^^ also so in etwa:
INSERT INTO zeiten (zeit) VALUES ($datum) WHERE prID='$prID' AND datum='$ts' AND user='$userid' AND (SELECT count(id) FROM zeiten WHERE prID='$prID' AND datum='$ts' AND user='$userid') = '0';

damit sollte wie gesagt nur ein insert erfolgen, wenn es den datensatz noch nicht gibt. bringt uns aber eben nicht automatisch zum update :/




edit3: was kuhl wäre, wäre sowas: ^^
Code:
UPDATE zeiten SET zeit='$datum' WHERE prID='$prID' AND datum='$ts' AND user='$userid' AND
    (INSERT INTO zeiten (zeit) VALUES ($datum) WHERE prID='$prID' AND datum='$ts' AND user='$userid' AND
        (SELECT count(id) FROM zeiten WHERE prID='$prID' AND datum='$ts' AND user='$userid') = '0'
    ) = failed
;
müsste man nur rausfinden, wie man feststellt, ob insert fehlgeschlagen is ><
 
Zuletzt bearbeitet:
^^ Hast du mein BTW gelesen? Ich fände das, wenn ich recht habe, immer noch um ein Vielfaches leichter als irgendwelche für mich kaum noch durchschaubaren querys zu basteln ...

Deinen Pseudocode hätte ich jetzt mal so umgesetzt:
PHP:
foreach($_POST as $key => $val) {
    if (startsWith($key, 'save')) {
        $prID = (int)substr($key, 4);
        if (isset($_POST['save'.$prID])) {
            mysqli_query($mysqli, "UPDATE projekte SET taetigkeit='".$_POST['taetigkeit']."', produkt='".$_POST['product']."', beschreibung='".$_POST['beschreibung']."' WHERE id='".$prID."'");
            for ($b = 0; $b < 7; $b++) {
                $ts = $wochenanfang + ($b * 60 * 60 * 24);
                $dauer = $_POST[$ts]; 
                if ($dauer == "") { 
                    mysqli_query($mysqli, "DELETE FROM zeiten WHERE user = userid AND datum = '$ts'");
                } else {
                    if (mysqli_query($mysqli, "SELECT * FROM zeiten WHERE user = userid AND datum = ts AND prID = prID")) {
                        mysqli_query($mysqli, "UPDATE zeiten SET zeit='".$dauer."' WHERE taetprodid='".$prID."' AND datum='".$ts."'");
                    } else {
                        mysqli_query($mysqli, "INSERT INTO zeiten (zeit) VALUES ('$dauer') WHERE taetprodid='".$prID."' AND datum='".$ts."'");
                    }
                }
            }
        }
    }
}
Funktioniert aber auch nicht.

Können wir eigentlich einfach so "user" und "userid" in den querys sagen? Müsste ich da nicht eher "user.id = $userid" sagen?
 
Zuletzt bearbeitet:
BTW: Ob DB-fragen, oder Website-Felder mit isset auf Inhalt abfragen, läuft doch aufs selbe hinaus?! Wenn ein Feld einen Inhalt hatte, dann muss genau dafür auch was in der DB stehen, ergo weiß ich --> UPDATE. Hatte ein Feld keinen Inhalt (isset()=false), kann auch nichts in der DB stehen, ergo --> INSERT.
Wieso also sollte mein Ansatz, den ich verstehen würde, nicht funktionieren? Warum die DB fragen?
wieso sollte es aufs selbe hinauslaufen? du editierst ja etwas, also änderst du etwas. und GESETZT sind die inputfelder alle! es kommt auf den inhalt an. nen leeren eintrag brauch man ned neu in die db einfügen, muss ihn aber ggf bei einem bestehenden ändern (eben editieren ^^).

nur wie willst du anhand der formular-inputs bestimmen, was in der db steht? >< das geht doch überhaupt nicht. stel dir vor, du kommst als kunde an einen eisstand und willst nen kiwi-eis (das ist deine editier-anweisung - dein wunsch an die db szs). aber nur weil du den wunsch nach einem kiwi-eis verspürst, heißt das doch noch lange nich, dass der eismann auch sowas hat. schon garnich, wenn du nich die frucht meinst :devil:

du sagts es ja selber: wenn ein feld einen inhalt HATTE! in dem moment wo er das aber editiert, ist doch der ehemalige eintrag verfälscht. du kannst vom verfälschten eintrag NICHT auf den in der db schließen. bzw nich verfälscht, halt geändert. du musst erstmal prüfen, wie die db ausieht. ich hab hier nen leeres inputfeld (es ist dennoch gesetzt - isset == true). was nu? wie sah das vorher aus? das weißt du doch garnich. wurde das geändert? wurde es nicht geändert? du kennst den originalwert nicht. daher: frag die db, wie der originale wert aussah - obs überhaupt einen gibt.


gut, nun zu deiner umsetzung: soweit ganz gut. aber das die sql's eben auch pseudocode waren... >< natürlich musste du user = userid mit deinen splatennamen und der entsprechenden variablen ersetzen xD also ich glaube userid='".$userid."'. soweit sieht das auch gut aus, allerdings musst du mein insert und update eben AUCH nach der user-id fragen (where). beim projekt fehlt die auch, aber da weiß ich jetz nich, ob das gewollt ist (wegen meiner anmerkung vorhin) und du da schon die userid rausgeshmissen hast oder obs auch da nen versehen is ^^
 
Irgendeinen " oder ' Syntaxfehler hat's in der INSERT-Zeile, sonst müsste es jetzt das sein, was du haben willst:
PHP:
foreach($_POST as $key => $val) {
    if (startsWith($key, 'save')) {
        $prID = (int)substr($key, 4);
        if (isset($_POST['save'.$prID])) {
            mysqli_query($mysqli, "UPDATE projekte SET taetigkeit='".$_POST['taetigkeit']."', produkt='".$_POST['product']."', beschreibung='".$_POST['beschreibung']."' WHERE id='".$prID."'");
            for ($b = 0; $b < 7; $b++) {
                $ts = $wochenanfang + ($b * 60 * 60 * 24);
                $dauer = $_POST[$ts]; 
                if ($dauer == "") { 
                    mysqli_query($mysqli, "DELETE FROM zeiten WHERE userid='".$userid."' AND datum='".$ts."'");
                } else {
                    if (mysqli_query($mysqli, "SELECT * FROM zeiten WHERE userid='".$userid."' AND datum='".$ts."' AND taetprodid='".$prID."'")) {
                        mysqli_query($mysqli, "UPDATE zeiten SET zeit='".$dauer."' WHERE taetprodid='".$prID."' AND datum='".$ts."' AND userid='".$userid."');
                    } else {
                        mysqli_query($mysqli, "INSERT INTO zeiten (zeit) VALUES ('$dauer') WHERE taetprodid='".$prID."' AND datum='".$ts."' AND userid='".$userid."'");
                    }
                }
            }
        }
    }
}
Wo sollte ich die userid rausgeschmissen haben? Die ist noch in allen DB-Tabellen drinnen.
 
Hui, der Code ist "gefährlich"! Die UPDATE Zeile bewirkt, warum auch immer, dass sämtliche Einträge in "zeiten" gelöscht werden! Ich habe nur "edit" geklickt, nen anderen Wert eingegeben, "save" ... alles weg! :wow:

Auch Tätigkeit, Produkt und Beschreibung wird nicht mehr angezeigt, obwohl das zumindest in "projekte" noch in der DB da ist.
 
kannste das nochmal alles zippen? klingt irgendwie so, als ob er in der db nix falsch macht, aber deine ausgeb irgendwie vom saven beeinflusst wird.
 
meh, jetz hab ich die db gelöscht und diesmal war keine bei dir zum importieren dabei xD

was mir bei deiner delete zeile auffällt: da fehlt die projekt id. so löscht du ALLE zeiten dieses datums von diesem user. also projektübergreifend.
 
hab grad noch in auswerten.php beim erstellen des "row collectors" was seltsamens von mir enddeckt:
PHP:
                    if (isset($row_collector[$taet_id]['data'][$prod_id]['time'][$ts])) {
                        $td[$i+3] = $row_collector[$taet_id]['data'][$prod_id]['time'][$ts];
                    } else {
                        $td[$i+3] = ' ';
                    }
mE ist der else-teil überflüssig, kA was ich damit bezwecken wollte ^^ kann bei der abfrage $datum == "" zu fehlern führen. entweder a) trim($datum) == "" fragen oder b) (int)$datum == 0 oder c) das else weglassen (würd ich eh empfehlen). am besten noch a oder b kombiniert mit c ^^

nu erstmal wieder die db bauen xD
 
^^ Okay.

Wenn du meinen Code nimmst, musst du in der DB nichts ändern. ;)

[EDIT]
$datum soll eigentlich $dauer sein, oder? Ich finde in meinem Code kein "$datum ==". Lediglich das "$dauer ==" in formular.php.
 
jop, hab auch grad des rätsels lösung entschlüselt: projekte ohne eingetragene zeiten in gewünschten zeitraum werden nicht angezeigt. und scheinbar löscht unser ausgeklügeltes system schlicht alle zeiten xD

edit: bringt mich glatt zu nem anderen problem *tippel*
wir könnten jetzt nur über einträge anlegen (also pze.php) zeiten hinzufügen. allerdings wird er dann vermutlich trotz gleicher taet-prod-kombi schlicht in neues projekt anlegen. wir müssen also auch bei confirm erstmal prüfen, ob ein passender eintrag bei den projekten schon vorhanden ist. also wieder ein select an die db, die diese taet-prod-kombi abfragt. gibts unsere kombi bereits, wird sie nur geupdated, ansonsten ge-inserted.

-> select * from projekte where tätigkeit = tID und produkt = pID (wieder reinster pseudocode :P ).


edit2: seh grad, du hast in der projekttabelle noch die userid drin. ich würde wie gesagt empfehlen die zu schmeisen. so können mehrere MA's an einem projekt arbeiten. also das sich das eben auch in der db niederschlägt. im endeffekt braucht man das nich pro user zu speichern, da der user-zusammenhang eh über die zeiten passiert. sprich, über zeiten kann ich locker rausfinden, welcher user an welchem projekt arbeitet, hab aber nich 20 mal das an und für sich gleiche projekt gespeichert.

hmm, ggf kannst du die userid spalte auch umbenennen in edit_user oder so. dann speicherst da die id desjenigen rein, der zuletzt was an dem projekt geändert hatte. DANN allerdings müsste man beim saven prüfen, ob sich auch was geändert hat, vorm update. das war bisher schlicht egal ^^ müssten wir also auch den projekte datensatz per select abfragen, dann das ergebnis der anfrage mit unseren übergebenen formulardingern vergleichen und NUR bei abweichungen wird geupdated. in where wird dabei NICHT nach dem user gesucht, aber er wird bei set mit bedacht (eben als letzter editor gespeichert). ggf kannste da auch edit_date als spalte noch hinzufügen, um rausfinden zu können, WANN es editiert wurde.

wieso der umstand?
wenn irgendwer schlicht seine zeiten editiert und am projekt an sich garnix ändert, dann würde er ohne diese prüfung dennoch als editor drin stehn. jemand der wirklich was am projekt geändert hat, kann somit ganz leicht überschrieben werden - und dann kann man sichs auch ganz schenken ^^
 
Zuletzt bearbeitet:
Hast du jetzt so gemeint?
Code:
if (isset($_POST['confirm'])) {
    for ($a = 1; $a <= $add; $a++) {
        $stunden = array("montag".$a."", "dienstag".$a."", "mittwoch".$a."", "donnerstag".$a."", "freitag".$a."", "samstag".$a."", "sonntag".$a."");
    
        $eintragen1 = mysqli_query($mysqli, "INSERT INTO projekte (taetigkeit,  produkt, userid, beschreibung, erstellt) VALUES ('".$_POST['taetigkeit'.$a]."', '".$_POST['product'.$a]."', '$userid', '".$_POST['beschreibung'.$a]."', '$erstellt')");  
        $taetprodid = mysqli_insert_id($mysqli);
        
        for ($b = 0; $b < 7; $b++) {
            $ts = $wochenanfang + ($b * 60 * 60 * 24);
            if (isset($_POST[$ts.'_'.$a]) and $_POST[$ts.'_'.$a] != "") {
                $dauer = $_POST[$ts.'_'.$a]; 
                [COLOR=blue][B]if (mysqli_query($mysqli, "SELECT * FROM projekte WHERE taetigkeit = taetigkeiten.id AND produkt = produkte.id") { [/B]                   
                    $eintragen2 = mysqli_query($mysqli, "INSERT INTO zeiten (userid, taetprodid, zeit, datum) VALUES ('$userid', '$taetprodid', '$dauer', '$ts')");
                [COLOR=blue][B]}[/B]            }
        }
    }
 }
    
function startsWith($haystack, $needle) {
    return $needle === "" || strpos($haystack, $needle) === 0;
}
    
foreach($_POST as $key => $val) {
    if (startsWith($key, 'save')) {
        $prID = (int)substr($key, 4);
        if (isset($_POST['save'.$prID])) {
            mysqli_query($mysqli, "UPDATE projekte SET taetigkeit='".$_POST['taetigkeit']."', produkt='".$_POST['product']."', beschreibung='".$_POST['beschreibung']."' WHERE id='".$prID."'");
            for ($b = 0; $b < 7; $b++) {
                $ts = $wochenanfang + ($b * 60 * 60 * 24);
                $dauer = $_POST[$ts]; 
                if ($dauer == "") { 
                    mysqli_query($mysqli, "DELETE FROM zeiten WHERE userid='".$userid."' AND datum='".$ts."' taetprodid='".$prID."'");
                } else {
                    if (mysqli_query($mysqli, "SELECT * FROM zeiten WHERE userid='".$userid."' AND datum='".$ts."' AND taetprodid='".$prID."'")) {
                        mysqli_query($mysqli, "UPDATE zeiten SET zeit='".$dauer."' WHERE taetprodid='".$prID."' AND datum='".$ts."' AND userid='".$userid."'");
                    } else {
                        mysqli_query($mysqli, "INSERT INTO zeiten (zeit) VALUES ('$dauer') WHERE taetprodid='".$prID."' AND datum='".$ts."' AND userid='".$userid."'");
                    }
                }
            }
        }
    }
}
Eigentlich if UPDATE else INSERT, schon klar, aber ich wollte nicht gleich alles umbauen, falls das ^^ schon nicht stimmt. Und komme ich so (taetigkeit = taetigkeiten.id) zu der id, die ich brauche? Vraiablen $pID und $tID habe ich (zumindest hier) nicht.
 
Zuletzt bearbeitet:
konnts jetz grad nich bei dir prüfen, wollte schnell meins fertig bekommen, muss jetz nämlich los. schau mal ob deines wie meins is. und: schau mal pls drüber, ob meine sql anfragen mit diesem mysqli zeugs so richtig is ^^ du hast damit mehr erfahrung wie ich xD jedenfalls prinzipiell so in etwa (beim einfügen neuer daten mittels confirm button:
PHP:
    if (isset($_POST['confirm'])) {
        for ($a = 1; $a <= $add; $a++) {
            //$stunden = array("montag".$a."", "dienstag".$a."", "mittwoch".$a."", "donnerstag".$a."", "freitag".$a."", "samstag".$a."", "sonntag".$a."");
    
            $check = mysqli_query($mysqli, "SELECT * FROM projekte WHERE taetigkeit='".$_POST['taetigkeit'.$a]."' AND produkt='".$_POST['product'.$a].";");
            if($check) {
                $row = mysqli_fetch_assoc($check);
                $taetprodid = row['id'];
                if($row['taetigkeit'] != $_POST['taetigkeit'.$a] or $row['produkt'] != $_POST['product'.$a] or $row['beschreibung'] != $_POST['beschreibung'.$a])
                    $eintragen1 = mysqli_query($mysqli, "UPDATE projekte SET taetigkeit='".$_POST['taetigkeit'.$a]."', produkt='".$_POST['product'.$a]."', userid='$userid', beschreibung='".$_POST['beschreibung'.$a]."', erstellt='$erstellt') WHERE id='$taetprodid';");  
            } else {
                $eintragen1 = mysqli_query($mysqli, "INSERT INTO projekte (taetigkeit, produkt, userid, beschreibung, erstellt) VALUES ('".$_POST['taetigkeit'.$a]."', '".$_POST['product'.$a]."', '$userid', '".$_POST['beschreibung'.$a]."', '$erstellt')");  
                $taetprodid = mysqli_insert_id($mysqli);
            }
        
            for ($b = 0; $b < 7; $b++) {
                $ts = $wochenanfang + ($b * 60 * 60 * 24);
                if (isset($_POST[$ts.'_'.$a]) and $_POST[$ts.'_'.$a] != "") {
                    $dauer = $_POST[$ts.'_'.$a];                              
                    $check = mysqli_query($mysqli, "SELECT * FROM zeiten WHERE taetprodid='".$taetprodid."' AND userid='".$userid."' AND datum='".$ts."';");
                    if($check) {
                        $row = mysqli_fetch_assoc($check);
                        if($row['zeit'] != $dauer)
                            $eintragen2 = mysqli_query($mysqli, "UPDATE zeiten SET zeit='".$dauer." WHERE id='".$row['zeit']."';"); 
                    } else
                        $eintragen2 = mysqli_query($mysqli, "INSERT INTO zeiten (userid, taetprodid, zeit, datum) VALUES ('$userid', '$taetprodid', '$dauer', '$ts')");
                }
            }
        }
    }
wie gesagt, muss jetz erstmal los, warscheinlich bis heut abend...
 
zu dem on update... das scheints nur für key zu geben? für eine beliebige spalte wäre es mMn sinnvoller. weil mit key können wir leider nix anfangen (wenn ich das richtig verstanden hab). einerseits wäre in der projekte-tabelle die prID zwar ein unique key, aber eben auch auto-increment. somit fiele das schonmal raus.

Einfach einen Unique Index aus userid, datum und taetprodid bauen.

EDIT: Gerade getestet, funktioniert wunderbar.
 
Zuletzt bearbeitet:
also quasi eine spalte "aushilfskey" xD als varchar mit dem wert $userid.$datum.$teatprodid? hmm, sollte unique sein joa. an solch einen workaround hatte ich jetz natürlich nich gedacht ^^ aber ich denke, das merken wir uns mal für optimierungen später vor. der aufgedröselte code ist denke am anfang leichter verständlich *denk*
 
Zurück