Jörg: Idee für Query gesucht

Hallo,

ich brauche eine Idee für eine Update-Query in mysql 8.

Und zwar habe ich ein Update, bei dem in eine Spalte über concat etwas wie "Strom für n KW Heizleistung" (n ist eine Ziffer von 1-6) als Beschreibung geschrieben wird.

Allerdings soll das nur dann dieser Spalte hinzugefügt werden, wenn es nicht bereits dort vermerkt ist.

Bisher fällt mir nur ein, vorher einen SELECT auf die Spalte ausztuführen, um zu ermitteln, ob der Satz schon drin steht. Oder die Spalte zuvor zu leeren, aber dann würde auch sämtlicher anderer Text daraus geleert, was ich ansich nicht will.

Hat einer von Euch eine gute Idee?

Jörg

  1. Hi,

    ich brauche eine Idee für eine Update-Query in mysql 8.

    Und zwar habe ich ein Update, bei dem in eine Spalte über concat etwas wie "Strom für n KW Heizleistung" (n ist eine Ziffer von 1-6) als Beschreibung geschrieben wird.

    Allerdings soll das nur dann dieser Spalte hinzugefügt werden, wenn es nicht bereits dort vermerkt ist.

    Bisher fällt mir nur ein, vorher einen SELECT auf die Spalte ausztuführen, um zu ermitteln, ob der Satz schon drin steht.

    was spricht dagegen, das in der WHERE-Clause des UPDATE-Statements zu machen?

    cu,
    Andreas a/k/a MudGuard

    1. Hi Andreas,

      was spricht dagegen, das in der WHERE-Clause des UPDATE-Statements zu machen?

      Es stehen noch weitere update-Statements in der Query, die dann auch nicht ausgeführt würden.

      Jörg

      1. Hallo Jörg,

        Oh. Das sehe ich jetzt erst.

        Das heißt: das UPDATE Statement aktualisiert - sagenwirmal - 5 Spalten und in die Textspalte soll der Vermerk nur hinein, wenn er noch nicht drinsteht.

        Möglichkeit 1: zwei Update-Statements. Das zweite findet die Daten vom ersten im Cache und ist dann ziemlich fix.

        Möglichkeit 2: IF Funktion. Wertet den ersten Parameter aus. Ist das Ergebnis TRUE (oder nicht 0), wird der zweite zurückgegeben, andernfalls der dritte.

        UPDATE tabelle
          SET foo = 1,
              bar = 2,
              text = IF(text RLIKE '.*Strom für [0-9]+ KW Heizleistung.*',
                        text,
                        CONCAT_WS(text, 'Strom für', n, 'KW Heizleistung')
              baz = 3
        WHERE id=4711
        

        Möglichkeit 3: Erwähnte ich schon die Datenmodellierung und Verzicht auf solche Hacks?

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Möglichkeit 3: Erwähnte ich schon die Datenmodellierung und Verzicht auf solche Hacks?

          Hallo Rolf,

          vielen Dank für Deine (doppelte) ausführliche Hilfe. Selbstverständlich hast Du Recht, dass das dieser Text ansich nicht in die DB gehört und das wird auch geändert. Nur dauert das noch 3-4 Wochen und hierfür brauche ich eine Art Überbrückung. Zudem lerne ich dabei ja auch etwas. 😉

          Ich denke, ich werde als Überbrückung die 2 Updates nehmen. Trotzdem danke auch für die Alternativen.

          Schönen (Rest)abend und Grüße

          Jörg

  2. Hallo Jörg,

    Hat einer von Euch eine gute Idee?

    Ja. Datenmodellierung. Eine solche Textspalte gehört nicht in eine Datenbank. Vor allem nicht, wenn da mehr als ein Textblock drinsteht.

    Wie kommt der Text da 'rein? Durch User-Eingabe? Was machst Du bei Tippfehlern?

    Wie findest Du Sätze mit einer Heizleistung von mehr als 5KW (zum Beispiel). Was ist bei 12KW? Oder 9,5?

    Und wenn er Eintrag drin ist: kann es sein, dass Du den Textbaustein aktualisieren können musst? Oder entfernen? Es wird immer gruseliger.

    Aber du sollst auch eine Idee für dein Konstrukt bekommen. Eine Möglichkeit wäre der Einsatz von LIKE.

    UPDATE tabelle
    SET text = CONCAT_WS(text, 'Strom für', n, 'KW Heizleistung')
    WHERE (...Identifikation des Satzes...)
      AND text NOT LIKE '%Strom für _ KW Heizleistung%'
    

    Du würdest also zunächst den Satz wie üblich identifizieren (über eine id oder sonst wie) und zusätzlich mit LIKE abfragen, ob ein bestimmtes Muster schon drin ist. Der Unterstrich passt nur auf genau ein Zeichen, aber hier ein % zu verwenden ist gefährlich, es könnte ja auch schon sowas drinstehen wie "Strom für Familie Müller, benötigt werden 7 KW Heizleistung". Ein % in der Mitte würde diesen Text matchen.

    Du könntest jetzt sagen: SO was kommt bei mir nicht vor, aber sei gewarnt, der Teufel ist ein Eichhörnchen und seine Nüsse findest Du überall.

    Eine Alternative ist der Einsatz der REGEXP_LIKE Funktion, oder ihrem Synonym, dem RLIKE Operator.

    UPDATE tabelle
    SET text = CONCAT_WS(text, 'Strom für', n, 'KW Heizleistung')
    WHERE (...Identifikation des Satzes...)
      AND text NOT RLIKE '.*Strom für [0-9]+ KW Heizleistung.*'
    

    Die Syntax für REGEXP-Patterns in mysql findest Du auf der verlinkten Seite weiter unten. [0-9]+ bedeutet: Ein Zeichen aus der Zeichenmenge 0-9 soll einmal oder mehrmals vorkommen. Damit würden auch 37KW Heizleistung möglich sein.

    Aber: Das ist nicht gut. Es ist nicht das, was man mit einer Datenbank tut. Wie man es besser macht, kann ich Dir nicht ohne tiefere Kenntnis deiner Daten sagen. Eventuell brauchst Du zusätzliche Spalten. Oder sogar eine 1:n angeschlossene Tabelle für Zusatz-Infos. Die Aufbereitung für die Anzeige findet dann in der Anwendung statt oder einem Zugriffs-Service, meinetwegen auch in einer Stored Procedure, aber es gehört definitiv nicht in die Table.

    Rolf

    --
    sumpsi - posui - obstruxi