supernewb: ASP + Access Datenbank + UPDATE COLUMN IF COLUMN IS NULL ELSE ...

Hi ihr Webmaster und code-Profis

ich arbeite an einer Website mit hinterlegter Datenbank in Access. Die Website ist in ASP geschrieben. Die Datenbank enthält Mitarbeiterinformationen samt Beauftragungen und sonstigen Informationen. Gerade die Beauftragungen (oder Verantwortlichkeiten, wie auch immer) sind im moment relevant.

Meine Tabelle heisst "Mitarbeiter" und hat etliche Columns wie "Name", "Vorname", "telefon", ...."Beauftragung", "Beauftragung2", Beauftragung3"

Ich möchte nun eine Funktion erstellen die ein UPDATE der "Beauftragungen,Beauftragungen2,Beauftragungen3" Columns durchführt. Ziel ist eine Prüfung beim UPDATE: So nach dem Motto

MM_editCmd.CommandText = "UPDATE Mitarbeiter IF/CASE WHEN Beauftragung IS NULL THEN Set Beauftragung = ? ELSE Beauftragung2 IS NULL THEN Set Beauftragung2 = ? ELSE Beauftragung3 IS NULL THEN Set Beauftragung3 = ? END WHERE ID = " & strID & " "

Es soll also geprüft werden, ob die Column "Beauftragung" in der Tabelle Mitarbeiter bei ID "strID" NULL ist. Wenn ja, soll der übermittelte Wert dort rein geschrieben werden. Wenn nein, dann soll Column "Beauftragung2" auf IS NULL geprüft und befüllt werden, un im ELSE Fall noch Beauftragung 3.

Ich habe das oben stehende Kommando mit "IF" "END IF" und "CASE WHEN" und "END" probiert, beides schmeißt aber Syntax error.

(80040e14|Syntaxfehler_in_UPDATE-Anweisung.)

Ohne diesen Prüfungsvorgang funktioniert die UPDATE Anweisung übrigens einwandfrei.

Kann mir jemand helfen ?

Grüße

  1. Hallo supernewb,

    ich kenne mich mit SQL aus, aber nicht mit Access. Dein Statement sieht nach Phantasie-Syntax aus und kann darum vermutlich nicht funktionieren.

    Die grundlegende UPDATE Syntax ist:

    UPDATE tabelle
    SET spaltenname=wert, spaltenname=wert,WHERE zeilenbedingung
    

    Du kannst da nicht beliebig Schlüsselworte hineinstreuen, du musst Dich an die vorgegebenen Sprach-Regeln halten.

    • der Spaltenname kann nicht variabel sein
    • der Wert muss als gültiger SQL-Ausdruck aufgebaut sein
    • Du kannst nicht Befehlsteile (wie SET spalte=wert) mit einem IF oder CASE in eine Bedingung setzen.

    Ich weiß nicht einmal, ob Access SQL einen CASE-Ausdruck im SELECT versteht. MS SQL Server kennt es, in Access-Beispielen taucht es auch auf, aber formal definiert ist es in der MSDN oder docs.microsoft.com nicht. Zumindest nicht da, wo ich zu suchen versucht habe. Die Zeiten, wo die Doku-Autoren von MS etwas geschrieben haben, das mir sinnvoll erschien, sind seit 15 Jahren vorbei.

    Ich würde Dir drei UPDATE-Befehle empfehlen:

    UPDATE Mitarbeiter SET Beauftragung=? WHERE ID=? AND Beauftragung IS NULL 
    UPDATE Mitarbeiter SET Beauftragung2=? WHERE ID=? AND Beauftragung2 IS NULL 
    UPDATE Mitarbeiter SET Beauftragung3=? WHERE ID=? AND Beauftragung3 IS NULL 
    

    Man kann das auch in ein UPDATE Statement packen:

    UPDATE Mitarbeiter 
    SET Beauftragung=IIF(Beauftragung is null, ?, Beauftragung),
        Beauftragung2=IIF(Beauftragung2 is null, ?, Beauftragung2),
        Beauftragung3=IIF(Beauftragung2 is null, ?, Beauftragung3),
    WHERE ID=?
    

    Da musst Du dann passend die Werte für die ? übergeben. Ob das komplexe Statement schneller ist als drei einzelne, weiß ich nicht. Musst Du ausprobieren.

    Wie Du dem MM_editCmd die Parameter passend beibringst, kann ich Dir nicht sagen. Wie gesagt, ich kene

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo Rolf und danke für deine Antwort. Phantasy-Syntax ist vielleicht etwas weit her geholt, aber im Kern nicht ganz falsch.

      Wie immer in solchen Situationen habe ich die Macht des Googlers zweckentfremdet, und wurde dort mehr oder weniger (eher weniger) fündig. Daher habe ich dann einfach rumprobiert.

      Dein Vorschlag mit dem 3 Befehlen scheint mir das sinnvollste zu sein. Ich werde das mal einarbeiten und probieren.

      Ich danke Dir :)

      1. hey nochmal, ich habe jetzt mal versucht die UPDATE Anweisungen in eigene editCmds zu packen (der originalquellcode ist übrigens von Dreamweaver), aber diese werden einfach nicht ausgeführt

        MM_editCmd.CommandText = "UPDATE Mitarbeiter SET Beauftragung=? WHERE ID= " & strID & " AND Beauftragung IS NULL " 
        MM_editCmd2.CommandText = "UPDATE Mitarbeiter SET Beauftragung2=? WHERE ID= " & strID & " AND Beauftragung IS NULL" 
        MM_editCmd3.CommandText = "UPDATE Mitarbeiter SET Beauftragung3=? WHERE ID= " & strID & " AND Beauftragung IS NULL "
        

        Variablen sind gesetzt, und execute auch

        Set MM_editCmd = MM_editCmd.Execute
        Set MM_editCmd2 = MM_editCmd2.Execute
        Set MM_editCmd3 = MM_editCmd3.Execute
        

        Set MM_editCmd = Server.CreateObject ("ADODB.Command") Set MM_editCmd2 = Server.CreateObject ("ADODB.Command") Set MM_editCmd3 = Server.CreateObject ("ADODB.Command")

        Hast du eventuell noch eine weitere Idee? Irgendwie muss der Sack doch zu überreden sein, die 2 weiteren UPDATE befehle auszuführen ... 😀 Grüße

        1. Hallo supernewb,

          Phantasy-Syntax ist vielleicht etwas weit her geholt

          Habe ich Dich damit verletzt? Das wollte ich nicht - aber trotzdem hast Du ein Statement in einer Syntax formuliert, die es nur in deiner Phantasie gibt. Es mag plausibel aussehen, ist aber von niemandem so vorgesehen worden und wird darum von Access nicht verstanden.

          UPDATE Anweisungen (...) werden einfach nicht ausgeführt

          Copy+Paste+Modify ist eine Kunst, die bis uns allen gerne mal schiefgeht. Ich gehe davon aus, dass deine Anweisungen ausgeführt werden. Sie haben lediglich nichts zu tun. Guck Dir die IS NULL Abfragen in den UPDATES 2 und 3 an. So, wie sie geschrieben sind, führen sie immer zu FALSE, da hast Du beim Anpassen der Kopie was übersehen.

          Rolf

          --
          sumpsi - posui - clusi
          1. nein, du hast mich nicht verletzt, Habe mich unglücklich ausgedrückt, alles gut 😉

            ich habe auch gefunden, was ich übersehen habe. Danke für den Hinweis. Es musste natürlich zum entsprechenden editcmd, cmd2 und cmd3 auch Beauftragung, Beauftragung2 und 3 heissen ..

            JETZT funktioniert das :) ABER ... Wenn Beauftragung 2 leer ist, und nun tatsächlich die Zelle beschrieben wird, ist Beauftragung3 natürlich auch leer, und wird ebenfalls beschrieben. Das ist natürlich ungewollt

            Wie kann jetzt festgelegt werden, dass nach einem erfolg schluss ist, und der nächste editCmd gar nicht ausgeführt wird? Der ist in diesem Fall natürlich immer wahr. wie beim batch? IF errorlevel=0 ... ?

            1. EDITH

              ein

              "UPDATE Mitarbeiter SET Beauftragung3=? WHERE ID= " & strID & " AND Beauftragung2 IS NOT NULL "
              

              macht genau das, was ich möchte 😀 Super duper. Ich danke Dir vielmals

              Wenn man hier nicht im Saft steckt und nur rudimentär Kenntnisse im scripten hat, sieht man meist den Wald vor lauter Bäumen nicht. Dazu ist der ASP Käse so alt und unmodern, dass ordentliche tutorials rar und uralt werden. Auf lange sicht muss ich wohl mal einen PHP Kurs machen

              Aber genug gejammert ... 😉

              Ich danke Dir vielmals Rolf, ohne Dich wäre ich da nicht drauf gekommen. 5 Sterne *****

              1. Hallo supernewb,

                das stimmt so nicht. Du würdest in diesem Fall Beauftragung 3 überschreiben, auch wenn es gefüllt ist.

                Mir war bisher die Verwendung deiner Felder nicht klar. Jetzt schon - und du erlebst hier die typischen Effekte einer unvollständigen DB-Normalisierung: Wenn es für einen Satz ein Attribut mehrfach gibt, gehört das eigentlich in eine separate Tabelle ausgelagert. Pseudo-Arrays in Form von "Dings1, Dings2, "Dings3" führen zu den hier auftretenden Problemen. Ob Du das tun willst, ist natürlich Deine Entscheidung.

                Eine naheliegende, aber potenziell gefährliche Lösung wäre, dass Du vor den Updates einen SELECT machst und dann schaust, welches der 3 Felder NULL ist. Passend dazu updatest Du dann das richtige Feld. ABER: Das geht nur, wenn Du der einzige User bist ODER Access Zugriff über Transaktionen mit Isolationsstufe SERIALIZABLE unterstützt. Wenn Du jetzt nicht weißt, wovon ich rede, dann lass die Finger davon :). Denn wenn Du nicht genau weißt, was Du tust, führt diese Lösung im Multiuser-Betrieb zu Datenfehlern.

                Zwei umständlichere, aber zuverlässigere Lösung könnten so aussehen:

                1. Verwende den RecordsAffected Zähler

                Ich weiß nicht ob Du von ACCESS diesen Zähler bekommst. Normalerweise meldet Dir eine SQL-Datenbank nach einem UPDATE, wieviele Zeilen aktualisiert wurden. Schau mal, ob dein MM_EditCmd Objekt eine Eigenschaft RecordsAffected hat.

                Wenn das größer als 0 ist, brauchst Du die restlichen Updates nicht mehr auszuführen. Auf diese Weise werden 1-3 Updates gemacht. Durch einen vorherigen SELECT kannst Du die Anzahl der Updates reduzieren, weil Du dann weißt, mit welchem Update du anfangen musst; und wenn alle Felder voll sind, brauchst Du gar nicht mehr zu updaten.

                Wenn es RecordsAffected nicht gibt:

                1. Führe die Updates geschickt aus

                Du kannst die Updates so formulieren, und zwar genau in dieser Reihenfolge:

                "UPDATE Mitarbeiter SET Beauftragung3=? WHERE ID= " & strID & " AND Beauftragung3 IS NULL AND Beauftragung2 IS NOT NULL"
                "UPDATE Mitarbeiter SET Beauftragung2=? WHERE ID= " & strID & " AND Beauftragung2 IS NULL AND Beauftragung IS NOT NULL"
                "UPDATE Mitarbeiter SET Beauftragung=? WHERE ID= " & strID & " AND Beauftragung IS NULL"
                

                Sind alle 3 Beauftragungsfelder NULL, führt nur das letzte Update zu einer DB-Änderung Ist Beauftragung gefüllt, aber Beauftragung2+3 NULL, wird Beauftragung2 geschrieben. Sind Beauftragung und Beauftragung2 gefüllt, aber Beauftragung3 ist NULL, wird Beauftragung3 geschrieben. Sind alle gefüllt, wird nichts geschrieben. Nachteil: Es werden immer 3 Updates gemacht.

                Das sieht alles umständlich aus, aber das ist angesichts einer potenziellen Multiuser-Umgebung und einer denormalisierten DB nicht vermeidbar.

                Rolf

                --
                sumpsi - posui - clusi
                1. da hast du natürlich recht. Und freilich, habe ich nicht verstanden worüber du schreibst (SERIALIZABLE ) 😝

                  Ich habe mir die Reihenfolge der Updates übernommen, und versuche noch eine Meldung zu generieren sobald 3 von 3 Feldern bereits belegt sind.

                  Ich danke Dir 😀