Jnnbo: PHPMyAdmin - SQL Befehl

Moin,

mir ist beim Eintragen leider in einem Script ein Fehler unterlaufen. Gibt es ein SQL Befehl den ich direkt in PHPMyAdmin ausführen kann, der folgendes erledigt:

Gehe in die Spalte p_bild suche dort alle Einträge die am Ende einen . haben und diese Zahl inkl. diesem Punk löschen.

Das Problem war, ich habe eine Variable gefüllt, obwohl kein Bild vorhanden war, daher hat er die Zufallszahl in die Datenbank gespeichert, was natürlich falsch ist.

Ich möchte ungern rund 6000 Artikel von Hand durchsuchen und einzeln löschen.

  1. Gehe in die Spalte p_bild suche dort alle Einträge die am Ende einen . haben und diese Zahl inkl. diesem Punk löschen.

    Klar, offensichtlich muss das eine UPDATE-Anfrage werden. Die Anfrage hat folgende Grundstruktur:

    UPDATE tablename
    SET p_bild = NULL
    WHERE /*Spalte p_bild endet auf einen Punkt*/
    

    Die Funktion, die nötig ist, um die Bedingung zu formulieren, findest du in der MySQL-Dokumentation.

    1. Hallo 1unitedpower,

      Klar, offensichtlich muss das eine UPDATE-Anfrage werden. Die Anfrage hat folgende Grundstruktur:

      UPDATE tablename
      SET p_bild = NULL
      WHERE /*Spalte p_bild endet auf einen Punkt*/
      

      hab mir erstmal alle anzeigen lassen was stand der Dinge ist

      SELECT * FROM `produkte` WHERE `p_bild` NOT REGEXP '.jpg' ORDER BY `p_bild` DESC
      

      Nach dem abschicken erhalte ich folgende Meldung

      Zeige Datensätze 0 - 24 (260 insgesamt, Die Abfrage dauerte 0.0071 Sekunden.) [p_bild: 997725287. - 598059163.]

      Hat also geklappt. Jetzt muss ich wie du geschrieben hast ein UPDATE machen. Ich sichere mir vorher aber die Datenbank, man weiß ja nie was am Ende rauskommt :)

      1. Tach!

        WHERE p_bild NOT REGEXP '.jpg'

        Dieser reguläre Ausdruck liefert dir vermutlich die passenden Ergebnisse, aber er ist nicht formal korrekt. Ein Punkt steht für „beliebiges Zeichen“. Wenn du einen Punkt meinst, musst du ihn maskieren. Das erfordert zwei Backslashes, weil einer bereits für den String '\.jpg' draufgeht und dann noch einer im regulären Ausdruck ankommt.

        dedlfix.

        1. Moin!

          Das erfordert zwei Backslashes, weil einer bereits für den String '\.jpg' draufgeht und dann noch einer im regulären Ausdruck ankommt.

          Nicht immer. Vergleiche

          <?php
          echo "\\n";
          echo '\n';
          

          Und kontrolliere:

          <?php
          $sql= '... WHERE p_bild NOT REGEXP "\.jpg$"';
          echo 'aus einfachen Quotas: ', $sql, "\n";
          $sql= "... WHERE p_bild NOT REGEXP '\.jpg$'";
          echo 'aus doppelten Quotas: ', $sql, "\n";
          
          

          Jörg Reinholz

          1. Tach!

            Das erfordert zwei Backslashes, weil einer bereits für den String '\.jpg' draufgeht und dann noch einer im regulären Ausdruck ankommt.

            Nicht immer. Vergleiche

            Der Kontext war SQL, nicht PHP.

            dedlfix.

            1. Moin!

              Das erfordert zwei Backslashes, weil einer bereits für den String '\.jpg' draufgeht und dann noch einer im regulären Ausdruck ankommt.

              Nicht immer. Vergleiche

              Der Kontext war SQL, nicht PHP.

              Sag nicht, Du hast es nicht gewollt:

              mysql> select name from pNamen where name regexp '\.ndrea';
              +---------+
              | name    |
              +---------+
              | Andreas |
              | Andrea  |
              +---------+
              2 rows in set (0.00 sec)
              
              mysql> select name from pNamen where name regexp '\\.ndrea';
              Empty set (0.00 sec)
              
              mysql> select name from pNamen where name regexp "\.ndrea";
              +---------+
              | name    |
              +---------+
              | Andreas |
              | Andrea  |
              +---------+
              2 rows in set (0.00 sec)
              
              mysql> select name from pNamen where name regexp "\\.ndrea";
              Empty set (0.00 sec)
              
              mysql> 
              
              

              Der backlash ging also nicht drauf.

              Jörg Reinholz

              1. Tach!

                Das erfordert zwei Backslashes, weil einer bereits für den String '\.jpg' draufgeht und dann noch einer im regulären Ausdruck ankommt.

                Der backlash ging also nicht drauf.

                Bitte? Der ist doch draufgegangen, wie deine Beispiele zeigen.

                mysql> select name from pNamen where name regexp '\.ndrea';
                +---------+
                | name    |
                +---------+
                | Andreas |
                | Andrea  |
                +---------+
                2 rows in set (0.00 sec)
                

                In beiden Namen ist kein . enthalten. Der Punkt wird nicht maskiert und steht damit für „beliebiges Zeichen“. In dem Fall matcht er auf das A.

                mysql> select name from pNamen where name regexp '\\.ndrea';
                Empty set (0.00 sec)
                

                Jetzt wird der Punkt maskiert, woraufhin dieser für sich selbst steht.

                PHP arbeitet anders als MySQL, wenn das maskierte Zeichen nicht in der Liste der Sonderzeichen (\r, \n, etc.) enthalten ist. In PHP ergibt "\." trotzdem "\.", in MySQL jedoch ".".

                dedlfix.

                1. @@dedlfix

                  In PHP ergibt "." trotzdem ".", in MySQL jedoch ".".

                  Und im Forum ergibt Kramdown Unsinn.

                  LLAP

                  --
                  „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                  1. Hallo Gunnar Bittersmann,

                    @@dedlfix

                    In PHP ergibt "." trotzdem ".", in MySQL jedoch ".".

                    Und im Forum ergibt Kramdown Unsinn.

                    Nö. Man muss nur den Kontextwechsel beachten. "Zeichen, die in kramdown eine besondere Bedeutung haben, müssen maskiert werden, wenn sie im Text verwendet werden sollen. Das Maskierungszeichen ist der Backslash (\)."

                    In PHP ergibt "\." trotzdem "\.", in MySQL jedoch ".".
                    In PHP ergibt "." trotzdem ".", in MySQL jedoch ".".

                    In PHP ergibt "\\." trotzdem "\\.", in MySQL jedoch ".".
                    In PHP ergibt "\." trotzdem "\.", in MySQL jedoch ".".

                    Bis demnächst
                    Matthias

                    --
                    Signaturen sind bloed (Steel) und Markdown ist mächtig.
                2. Moin!

                  Jetzt wird der Punkt maskiert, woraufhin dieser für sich selbst steht.

                  PHP arbeitet anders als MySQL, wenn das maskierte Zeichen nicht in der Liste der Sonderzeichen (\r, \n, etc.) enthalten ist.

                  In PHP ergibt "\." trotzdem "\.", in MySQL jedoch ".".

                  (wohl gemeint: ?)

                  In PHP ergibt "\." trotzdem "\.", in MySQL jedoch ".".

                  Du hast sogar Recht. Beweis:

                  mysql> select * from pNamen where name not regexp "\.jpg$"; 
                  +----+---------+
                  | id | name    |
                  +----+---------+
                  |  1 | Andreas |
                  +----+---------+
                  1 row in set (0.00 sec)
                  
                  mysql> select * from pNamen where name not regexp "\\.jpg$";
                  +----+------------+
                  | id | name       |
                  +----+------------+
                  |  1 | Andreas    |
                  |  6 | Andrea_jpg |
                  +----+------------+
                  2 rows in set (0.00 sec)
                  

                  Aber was zum Teufel soll dann das hier:

                  mysql> select * from pNamen where name regexp "\\\.jpg$";
                  +----+------------+
                  | id | name       |
                  +----+------------+
                  |  2 | Bernd.jpg  |
                  |  3 | Carmen.jpg |
                  |  4 | Detlev.jpg |
                  |  5 | Andrea.jpg |
                  +----+------------+
                  4 rows in set (0.00 sec)
                  

                  Jörg Reinholz

                  1. Tach!

                    PHP arbeitet anders als MySQL, wenn das maskierte Zeichen nicht in der Liste der Sonderzeichen (\r, \n, etc.) enthalten ist.

                    In PHP ergibt "\." trotzdem "\.", in MySQL jedoch ".".

                    (wohl gemeint: ?)

                    In PHP ergibt "\." trotzdem "\.", in MySQL jedoch ".".

                    Ich meinte einen Backslash gefolgt von einem Punkt (bei PHP in doppelten Anführungszeichen). PHP ignoriert die ungültige Escape-Sequenz und lässt beide Zeichen stehen, MySQL ignoriert den Backslash weg. (Aufgrund Gunnars Antwort korrigierte ich meine so, dass nun angezeigt wird, was ich zeigen wollte.)

                    Aber was zum Teufel soll dann das hier:

                    mysql> select * from pNamen where name regexp "\\\.jpg$";
                    

                    Kontext ist erstmal der Statement-Parser. Die ersten beiden Backslashes sind die Escape-Sequenz für einen literalen Backslash. Die nachfolgende Sequenz Backslash-Punkt ergibt einen Punkt. Das ist eine ungültige Escapesequenz und da wird der Backslash wegignoriert. Ergebnis ist also Backslash-Punkt, das von der Regex-Maschine als literaler Punkt angesehen wird.

                    dedlfix.

                    1. Moin!

                      Das ist eine ungültige Escapesequenz und da wird der Backslash wegignoriert.

                      DAS und vor allem, dass das stillschweigend passiert, meinte ich mit "zum Teufel"!

                      Jörg Reinholz

                      1. Tach!

                        Das ist eine ungültige Escapesequenz und da wird der Backslash wegignoriert.

                        DAS und vor allem, dass das stillschweigend passiert, meinte ich mit "zum Teufel"!

                        Stillschweigend? Jedenfalls ist das dokumentiertes Verhalten (kurz vor der Tabelle).

                        dedlfix.

                        1. Moin!

                          Stillschweigend?

                          Stillschweigend. Keine Fehlermeldung. Keine, in solchen Fällen (Veränderung der Anfrage!) fällige, Warnung.

                          Jedenfalls ist das dokumentiertes Verhalten (kurz vor der Tabelle).

                          Kommt mir vor, wie:

                          "Wir haben Sie doch auf Seite 1745 der in unserer Zentrale in Kibuktu ausliegenden AGB, mit jedem Mikroskop erkennbar (und sogar blassrosa auf grau hervorgehoben dargestellt!) zudem nicht nur in der verbreiteten Sprache Suaheli sondern auch der Übersetzung auf Khmer deutlichst darauf hingewiesen, dass Sie mit dem einmaligen Kauf des Waschpulvers ein Abonnement über eine Waschmaschine pro Monat eingehen!"

                          Zum Teufel, zum Teufel, zum Teufel!

                          Jörg Reinholz

                          1. Tach!

                            Stillschweigend?

                            Stillschweigend. Keine Fehlermeldung, keine, in solchen Fällen (Veränderung der Anfrage) fällige Warnung.

                            Ich weiß nicht, was dein Problem daran ist. \r, \n und die anderen Sequenzen verändern genauso stillschweigend aber dokumentiert zwei Zeichen zu einem. Und da wo dieses Verhalten dokumentiert ist, ist auch die Regel für Nicht-Sequenzen dokumentiert. - In allen mir bekannten Sprachen, die das so handhaben.

                            dedlfix.

                            1. Moin!

                              Ich weiß nicht, was dein Problem daran ist.

                              Weil einfach stillschweigend ein Zeichen aus der Anfrage entfernt und der Inhalt der Abfrage damit unkontrollierbar verändert wird? Kann ich nicht gut finden: Ist, war und bleibt des Teufels.

                              Jörg Reinholz

      2. Moin!

        SELECT * FROM `produkte` WHERE `p_bild` NOT REGEXP '.jpg' ORDER BY `p_bild` DESC
        

        Vermutlich willst Du alle Datensätze, die nicht auf '.jpg' enden. Und Du verwendest einen regulären Ausdruck.

        1. Der Punkt steht also für ein beliebiges Zeichen.
        2. Du hast nicht gezeigt, wo das String-Ende sein soll.

        Das matcht also auch auf einen Eintrag "foojpg1000" - bzw. matcht es nicht (NOT REGEXP) obwohl die Endung fehlt.

        Also muss Dein regulärer Ausdruck konkretisiert werden. Das $ zeigt das Ende und dem Punkt wird die Bedeutung von "beliebiges Zeichen" durch einen vorangestellten Backslash genommen:

        \.jpg$
        

        Auch wenn es im Testlauf zufällig geht und vielleicht dank einer überschaubaren Anzahl Datensätzen überprüfbar ist: Spätestens wenn das womöglich mal wiederholt werden soll, dann können andere Daten hier zu einem falschen (unvollständigen) Ergebnis führen.

        UPDATE `produkte` SET `p_bild` = CONCAT (`p_bild`, '.jpg') WHERE `p_bild` NOT REGEXP '\.jpg$';
        

        Hinweise:

        1. In CONCAT () ist es ein normaler String, kein Regex.
        2. CONCAT

        Jörg Reinholz

        1. Moin!

          Aus den von Dedlfix genannten und von mir bestätigten Gründen ist das hier

          UPDATE `produkte` SET `p_bild` = CONCAT (`p_bild`, '.jpg') WHERE `p_bild` NOT REGEXP '\.jpg$';
          

          zu korrigieren:

          UPDATE `produkte` SET `p_bild` = CONCAT (`p_bild`, '.jpg') WHERE `p_bild` NOT REGEXP '\\.jpg$';
          

          Jörg Reinholz

    2. Tach!

      Ergänzend dazu:

      UPDATE tablename
      SET p_bild = NULL
      WHERE /*Spalte p_bild endet auf einen Punkt*/
      

      Die Funktion, die nötig ist, um die Bedingung zu formulieren, findest du in der MySQL-Dokumentation.

      Bevor man ein Statement, dessen Auswirkungen man noch nicht genau kennt, auf den Produktivdatenbestand abfeuert, ist es günstig, ein SELECT mit demselben WHERE abzuschicken. (Außerdem hat man ja noch eine Kopie der Daten gesichert.) Das SELECT sollte nun genau die Daten bringen, die geändert werden sollen. Damit ist die WHERE-Klausel korrekt für das Anliegen formuliert.

      Wenn die Daten außerdem nicht nur sehr einfach geändert werden sollen, sondern mit Funktionsaufrufen oder ähnlich komplexen Rechnungen umgeformt werden sollen, kann man diese Umformung in den SELECT-Teil nehmen und sich somit die potenziellen Ergebnisse anschauen. Dann weiß man nicht nur, dass das WHERE richtig ist, sondern auch das SET vom UPDATE.

      dedlfix.