Wie ersetze ich einen regulären Ausdruck in MySQL?

516

Ich habe eine Tabelle mit ~ 500k Zeilen; Die Spalte varchar (255) UTF8 filenameenthält einen Dateinamen.

Ich versuche, verschiedene seltsame Zeichen aus dem Dateinamen zu entfernen - dachte, ich würde eine Zeichenklasse verwenden: [^a-zA-Z0-9()_ .\-]

Gibt es in MySQL eine Funktion, mit der Sie durch einen regulären Ausdruck ersetzen können ? Ich suche nach einer ähnlichen Funktionalität wie die Funktion REPLACE () - es folgt ein vereinfachtes Beispiel:

SELECT REPLACE('stackowerflow', 'ower', 'over');

Output: "stackoverflow"

/* does something like this exist? */
SELECT X_REG_REPLACE('Stackoverflow','/[A-Zf]/','-'); 

Output: "-tackover-low"

Ich weiß über REGEXP / RLIKE Bescheid , aber diese prüfen nur, ob es eine Übereinstimmung gibt, nicht, was die Übereinstimmung ist.

(Ich könnte ein " SELECT pkey_id,filename FROM foo WHERE filename RLIKE '[^a-zA-Z0-9()_ .\-]'" aus einem PHP-Skript machen, ein " preg_replaceund dann" UPDATE foo ... WHERE pkey_id=..."machen, aber das sieht aus wie ein langsamer und hässlicher Hack der letzten Instanz)

Piskvor verließ das Gebäude
quelle
8
Es handelt sich um eine Funktionsanforderung seit 2007: bugs.mysql.com/bug.php?id=27389 . Wenn Sie diese Funktion wirklich möchten, melden Sie sich an und klicken Sie auf die Schaltfläche "Betrifft mich". Hoffentlich bekommt es genug Stimmen.
TMS
4
@Tomas: Das habe ich getan ... im Jahr 2009, als ich mich danach umgesehen habe. Da es keine Fortschritte gab - anscheinend ist es kein so wichtiges Merkmal. (Übrigens hat Postgres es: stackoverflow.com/questions/11722995/… )
Piskvor verließ das Gebäude am
1
Verwandte, einfachere Version dieser Frage: stackoverflow.com/questions/6942973/…
Kzqai
2
Ich habe regexp_split(Funktion + Prozedur) & erstellt regexp_replace, die mit REGEXPOperator implementiert werden. Für einfache Suchvorgänge reicht es aus. Sie finden es vielleicht hier - also ist dies der Weg mit gespeichertem MySQL-Code, ohne UDF. Wenn Sie Fehler finden, die nicht durch bekannte Einschränkungen abgedeckt sind, können Sie das Problem gerne öffnen.
Alma Do
1
Diese Bibliothek wurde von einem anderen SO-Thread gefunden: github.com/mysqludf/lib_mysqludf_preg funktioniert einwandfrei.
Kyle

Antworten:

78

Mit MySQL 8.0+ können Sie die native REGEXP_REPLACEFunktion verwenden.

12.5.2 Reguläre Ausdrücke :

REGEXP_REPLACE(expr, pat, repl[, pos[, occurrence[, match_type]]])

Ersetzt Vorkommen in der Zeichenkette expr , die den regulären Ausdruck durch das Muster angegebenen übereinstimmen pat mit dem Ersatz - String repl , und gibt den resultierenden String. Wenn expr , pat oder repl ist NULL, ist der Rückgabewert NULL.

und Unterstützung für reguläre Ausdrücke :

Zuvor verwendete MySQL die Henry Spencer-Bibliothek für reguläre Ausdrücke, um Operatoren für reguläre Ausdrücke ( REGEXP, RLIKE) zu unterstützen.

Die Unterstützung für reguläre Ausdrücke wurde mithilfe von International Components for Unicode (ICU) neu implementiert. Diese bietet vollständige Unicode-Unterstützung und ist multibyte-sicher. Die REGEXP_LIKE()Funktion führt einen regulären Ausdrucksabgleich in der Art der Operatoren REGEXPund durch RLIKE, die jetzt Synonyme für diese Funktion sind. Darüber hinaus ist die REGEXP_INSTR(), REGEXP_REPLACE(), und REGEXP_SUBSTR() sind Funktionen zur Verfügung Spiel Positionen zu finden , und die Substitution und Extraktion perform String, respectively.

SELECT REGEXP_REPLACE('Stackoverflow','[A-Zf]','-',1,0,'c'); 
-- Output:
-tackover-low

DBFiddle Demo

Lukasz Szozda
quelle
147

MySQL 8.0+ :

Sie können die native REGEXP_REPLACEFunktion verwenden.

Ältere Versionen:

Sie können eine benutzerdefinierte Funktion ( UDF ) wie mysql-udf-regexp verwenden .

Jeremy Stein
quelle
3
REGEXP_REPLACE als benutzerdefinierte Funktion? Sieht vielversprechend aus, wird sich darum kümmern. Vielen Dank!
Piskvor verließ das Gebäude am
15
Leider scheint mysql-udf-regexp keine Unterstützung für Multibyte-Zeichen zu haben. regexp_replace ('äöõü', 'ä', '') gibt eine lange numerische Zeichenfolge anstelle von echtem Text zurück.
lkraav
3
MySQL selbst unterstützt mit seinen RegEx-Funktionen keine Multi-Byte-Zeichen.
Brad
4
Windows-Benutzer: Die hier verlinkte UDF-Bibliothek scheint keine gute Windows-Unterstützung zu haben. Die beschriebene Windows-Installationsmethode hat bei mir nicht gut funktioniert.
Jonathan
2
@lkraav Sie sollten die Bibliothek lib_mysqludf_preg unten ausprobieren, da sie hervorragend funktioniert. Dies ist die ausführliche Version, da sie standardmäßig einen Blob zurückgibt und ich nicht weiß, ob Sie einen Multibyte-Zeichensatz als Standard haben: Wählen Sie cast (TR als char) COLLATE utf8_unicode_ci aus (wählen Sie preg_replace ('/ ä /', '', 'öõüä') R) T
gillyspy
124

Verwenden Sie stattdessen MariaDB. Es hat eine Funktion

REGEXP_REPLACE(col, regexp, replace)

Siehe MariaDB-Dokumente und PCRE-Verbesserungen für reguläre Ausdrücke

Beachten Sie, dass Sie auch die Regexp-Gruppierung verwenden können (ich fand das sehr nützlich):

SELECT REGEXP_REPLACE("stackoverflow", "(stack)(over)(flow)", '\\2 - \\1 - \\3')

kehrt zurück

over - stack - flow
Benvorth
quelle
12
Dies ist von Mariadb 10
Nick
6
Für das nächste Mal, wenn ich es brauche, ist hier die Syntax zum Ändern einer ganzen Spalte: UPDATE table SET Name = REGEXP_REPLACE(Name, "-2$", "\\1")Dadurch wird -2 aus abcxyz-2 auf einmal aus einer ganzen Spalte entfernt.
Josiah
27
Das Ändern einer gesamten Plattform ist kaum eine realistische Lösung.
David Baucum
3
@DavidBaucum MariaDB ist ein Ersatz für MySQL. Es handelt sich also nicht um einen "Plattformwechsel", sondern eher um die Auswahl einer anderen Fluggesellschaft für dieselbe Reise
Benvorth,
3
@Benvorth MySQL 8.0 unterstützt es auch .
Lukasz Szozda
113

Meine Brute-Force-Methode, um dies zum Laufen zu bringen, war nur:

  1. Den Tisch wegwerfen - mysqldump -u user -p database table > dump.sql
  2. Suchen und Ersetzen find /path/to/dump.sql -type f -exec sed -i 's/old_string/new_string/g' {} \;einiger Muster - Es gibt offensichtlich andere reguläre Perl-Ausdrücke, die Sie auch für die Datei ausführen können.
  3. Tabelle importieren - mysqlimport -u user -p database table < dump.sql

Wenn Sie sicherstellen möchten, dass sich die Zeichenfolge nicht an einer anderen Stelle in Ihrem Dataset befindet, führen Sie einige reguläre Ausdrücke aus, um sicherzustellen, dass sie alle in einer ähnlichen Umgebung vorkommen. Es ist auch nicht so schwierig, ein Backup zu erstellen, bevor Sie einen Ersatz ausführen, falls Sie versehentlich etwas zerstören, das an Informationstiefe verliert.

Ryan Ward
quelle
33
Okay, das sollte auch funktionieren. Ich habe nicht in Betracht gezogen, offline zu ersetzen. Nettes Out-of-the-Box-Denken dort!
Piskvor verließ das Gebäude
10
Mir kommt es seltsam vor, dass Sie find so verwenden würden. Ich würde den Befehl auf sed -is / old_string / new_string / g '/path/to/dump.sql
speshak
36
Sehr riskant und unpraktisch bei großen Datenmengen oder bei vorhandener referenzieller Integrität: Um die Daten zu entfernen und dann erneut einzufügen, müssen Sie die referenzielle Integrität deaktivieren und in der Praxis auch Ihre Datenbank deaktivieren.
Raul Luna
5
Nachdem ich diese Methode in der Vergangenheit angewendet habe, stimme ich Raul zu, das ist sehr riskant. Sie müssen auch absolut sicher sein, dass sich Ihre Zeichenfolge nicht an einer anderen Stelle in Ihrem Datensatz befindet.
Eggmatters
1
Jahre zu spät zur Antwort @speshak, aber der Grund, warum ich mich für den Zugriff auf diese Datei entschieden habe, war, dass ich ursprünglich aus den oben genannten Gründen sehr nervös war. Zu der Zeit schien es so, als würde das Trennen des Teils "Datei finden" vom Teil "Ersetzen" den Code leichter lesbar machen, bevor ich ihn abschickte
Ryan Ward,
42

Wir lösen dieses Problem ohne Verwendung von Regex. Diese Abfrage ersetzt nur die exakte Übereinstimmungszeichenfolge.

update employee set
employee_firstname = 
trim(REPLACE(concat(" ",employee_firstname," "),' jay ',' abc '))

Beispiel:

emp_id employee_firstname

1 jay

2 jay ajay

3 jay

Nach dem Ausführen des Abfrageergebnisses:

emp_id employee_firstname

1 abc

2 abc ajay

3 abc

Jay Patel
quelle
@yellowmelon wofür sind die beiden Paare von doppelten Anführungszeichen?
Codecowboy
5
Er füllt den Namen des Mitarbeiters mit Leerzeichen davor und danach. Dies ermöglicht es ihm, nach (Leerzeichen) Employeename (Leerzeichen) zu suchen und zu ersetzen, wodurch vermieden wird, dass der Employeename "jay" abgefangen wird, wenn er Teil einer größeren Zeichenfolge "ajay" ist. Dann schneidet er die Räume aus, wenn er fertig ist.
Slam
42

Ich habe kürzlich eine MySQL-Funktion geschrieben, um Zeichenfolgen durch reguläre Ausdrücke zu ersetzen. Sie finden meinen Beitrag an folgender Stelle:

http://techras.wordpress.com/2011/06/02/regex-replace-for-mysql/

Hier ist der Funktionscode:

DELIMITER $$

CREATE FUNCTION  `regex_replace`(pattern VARCHAR(1000),replacement VARCHAR(1000),original VARCHAR(1000))
RETURNS VARCHAR(1000)
DETERMINISTIC
BEGIN 
 DECLARE temp VARCHAR(1000); 
 DECLARE ch VARCHAR(1); 
 DECLARE i INT;
 SET i = 1;
 SET temp = '';
 IF original REGEXP pattern THEN 
  loop_label: LOOP 
   IF i>CHAR_LENGTH(original) THEN
    LEAVE loop_label;  
   END IF;
   SET ch = SUBSTRING(original,i,1);
   IF NOT ch REGEXP pattern THEN
    SET temp = CONCAT(temp,ch);
   ELSE
    SET temp = CONCAT(temp,replacement);
   END IF;
   SET i=i+1;
  END LOOP;
 ELSE
  SET temp = original;
 END IF;
 RETURN temp;
END$$

DELIMITER ;

Beispielausführung:

mysql> select regex_replace('[^a-zA-Z0-9\-]','','2my test3_text-to. check \\ my- sql (regular) ,expressions ._,');
rasika godawatte
quelle
25
Ich werde nur den obigen Punkt verstärken: Diese Funktion ersetzt Zeichen , die einem Einzelzeichenausdruck entsprechen. Es heißt oben, dass es verwendet wird, um "Zeichenfolgen mit regulären Ausdrücken neu zu sortieren", und das kann ein wenig irreführend sein. Es macht seinen Job, aber es ist nicht der Job, nach dem gefragt wird. (Keine Beschwerde - es ist nur, um führende Menschen auf dem falschen Weg zu retten)
Jason
2
Es wäre hilfreicher, Code in Ihre Antwort aufzunehmen, als einen nackten Link zu posten.
Phobie
2
Schön - aber leider nicht mit Referenzen wie select regex_replace('.*(abc).*','\1','noabcde')(gibt 'noabcde' zurück, nicht 'abc').
Izzy
@phobie jemand anderes hat das in dieser Antwort getan - nur als Referenz für den Fall, dass der Link stirbt;)
Izzy
Ich habe diese Methode geändert, um zu versuchen, einige der oben genannten und weitere Einschränkungen zu beheben. Bitte sehen Sie diese Antwort .
Steve Chambers
14

Ich freue mich, Ihnen mitteilen zu können, dass es seit der Beantwortung dieser Frage eine zufriedenstellende Antwort gibt! Schauen Sie sich dieses tolle Paket an:

https://github.com/mysqludf/lib_mysqludf_preg

Beispiel-SQL:

SELECT PREG_REPLACE('/(.*?)(fox)/' , 'dog' , 'the quick brown fox' ) AS demo;

Ich habe das Paket aus diesem Blog-Beitrag gefunden, das auf diese Frage verlinkt ist .

dotancohen
quelle
13

UPDATE 2: In MySQL 8.0 wurde jetzt ein nützlicher Satz von Regex-Funktionen bereitgestellt, einschließlich REGEXP_REPLACE . Dies macht das Lesen unnötig, es sei denn, Sie müssen eine frühere Version verwenden.


UPDATE 1: Habe dies jetzt zu einem Blog-Beitrag gemacht: http://stevettt.blogspot.co.uk/2018/02/a-mysql-regular-expression-replace.html


Das Folgende erweitert die von Rasika Godawatte bereitgestellte Funktion, durchläuft jedoch alle erforderlichen Teilzeichenfolgen, anstatt nur einzelne Zeichen zu testen:

-- ------------------------------------------------------------------------------------
-- USAGE
-- ------------------------------------------------------------------------------------
-- SELECT reg_replace(<subject>,
--                    <pattern>,
--                    <replacement>,
--                    <greedy>,
--                    <minMatchLen>,
--                    <maxMatchLen>);
-- where:
-- <subject> is the string to look in for doing the replacements
-- <pattern> is the regular expression to match against
-- <replacement> is the replacement string
-- <greedy> is TRUE for greedy matching or FALSE for non-greedy matching
-- <minMatchLen> specifies the minimum match length
-- <maxMatchLen> specifies the maximum match length
-- (minMatchLen and maxMatchLen are used to improve efficiency but are
--  optional and can be set to 0 or NULL if not known/required)
-- Example:
-- SELECT reg_replace(txt, '^[Tt][^ ]* ', 'a', TRUE, 2, 0) FROM tbl;
DROP FUNCTION IF EXISTS reg_replace;
DELIMITER //
CREATE FUNCTION reg_replace(subject VARCHAR(21845), pattern VARCHAR(21845),
  replacement VARCHAR(21845), greedy BOOLEAN, minMatchLen INT, maxMatchLen INT)
RETURNS VARCHAR(21845) DETERMINISTIC BEGIN 
  DECLARE result, subStr, usePattern VARCHAR(21845); 
  DECLARE startPos, prevStartPos, startInc, len, lenInc INT;
  IF subject REGEXP pattern THEN
    SET result = '';
    -- Sanitize input parameter values
    SET minMatchLen = IF(minMatchLen < 1, 1, minMatchLen);
    SET maxMatchLen = IF(maxMatchLen < 1 OR maxMatchLen > CHAR_LENGTH(subject),
                         CHAR_LENGTH(subject), maxMatchLen);
    -- Set the pattern to use to match an entire string rather than part of a string
    SET usePattern = IF (LEFT(pattern, 1) = '^', pattern, CONCAT('^', pattern));
    SET usePattern = IF (RIGHT(pattern, 1) = '$', usePattern, CONCAT(usePattern, '$'));
    -- Set start position to 1 if pattern starts with ^ or doesn't end with $.
    IF LEFT(pattern, 1) = '^' OR RIGHT(pattern, 1) <> '$' THEN
      SET startPos = 1, startInc = 1;
    -- Otherwise (i.e. pattern ends with $ but doesn't start with ^): Set start pos
    -- to the min or max match length from the end (depending on "greedy" flag).
    ELSEIF greedy THEN
      SET startPos = CHAR_LENGTH(subject) - maxMatchLen + 1, startInc = 1;
    ELSE
      SET startPos = CHAR_LENGTH(subject) - minMatchLen + 1, startInc = -1;
    END IF;
    WHILE startPos >= 1 AND startPos <= CHAR_LENGTH(subject)
      AND startPos + minMatchLen - 1 <= CHAR_LENGTH(subject)
      AND !(LEFT(pattern, 1) = '^' AND startPos <> 1)
      AND !(RIGHT(pattern, 1) = '$'
            AND startPos + maxMatchLen - 1 < CHAR_LENGTH(subject)) DO
      -- Set start length to maximum if matching greedily or pattern ends with $.
      -- Otherwise set starting length to the minimum match length.
      IF greedy OR RIGHT(pattern, 1) = '$' THEN
        SET len = LEAST(CHAR_LENGTH(subject) - startPos + 1, maxMatchLen), lenInc = -1;
      ELSE
        SET len = minMatchLen, lenInc = 1;
      END IF;
      SET prevStartPos = startPos;
      lenLoop: WHILE len >= 1 AND len <= maxMatchLen
                 AND startPos + len - 1 <= CHAR_LENGTH(subject)
                 AND !(RIGHT(pattern, 1) = '$' 
                       AND startPos + len - 1 <> CHAR_LENGTH(subject)) DO
        SET subStr = SUBSTRING(subject, startPos, len);
        IF subStr REGEXP usePattern THEN
          SET result = IF(startInc = 1,
                          CONCAT(result, replacement), CONCAT(replacement, result));
          SET startPos = startPos + startInc * len;
          LEAVE lenLoop;
        END IF;
        SET len = len + lenInc;
      END WHILE;
      IF (startPos = prevStartPos) THEN
        SET result = IF(startInc = 1, CONCAT(result, SUBSTRING(subject, startPos, 1)),
                        CONCAT(SUBSTRING(subject, startPos, 1), result));
        SET startPos = startPos + startInc;
      END IF;
    END WHILE;
    IF startInc = 1 AND startPos <= CHAR_LENGTH(subject) THEN
      SET result = CONCAT(result, RIGHT(subject, CHAR_LENGTH(subject) + 1 - startPos));
    ELSEIF startInc = -1 AND startPos >= 1 THEN
      SET result = CONCAT(LEFT(subject, startPos), result);
    END IF;
  ELSE
    SET result = subject;
  END IF;
  RETURN result;
END//
DELIMITER ;

Demo

Rextester Demo

Einschränkungen

  1. Diese Methode wird natürlich eine Weile dauern, wenn die Betreffzeichenfolge groß ist. Update: Jetzt wurden minimale und maximale Übereinstimmungslängenparameter hinzugefügt, um die Effizienz zu verbessern, wenn diese bekannt sind (Null = unbekannt / unbegrenzt).
  2. Es wird nicht die Substitution von Rückreferenzierungen (zB erlauben \1, \2 etc.) erfassen Gruppen zu ersetzen. Wenn diese Funktionalität benötigt wird, lesen Sie bitte diese Antwort die versucht, eine Problemumgehung bereitzustellen, indem Sie die Funktion aktualisieren, um ein sekundäres Suchen und Ersetzen innerhalb jeder gefundenen Übereinstimmung zu ermöglichen (auf Kosten einer erhöhten Komplexität).
  3. Wenn ^und / oder $im Muster verwendet wird, müssen sie ganz am Anfang bzw. am Ende stehen - z. B. Muster, (^start|end$)die nicht unterstützt werden.
  4. Es gibt ein "gieriges" Flag, um anzugeben, ob die Gesamtübereinstimmung gierig oder nicht gierig sein soll. Das Kombinieren von gierigem und faulem Matching in einem einzelnen regulären Ausdruck (z. B. a.*?b.*) wird nicht unterstützt.

Anwendungsbeispiele

Die Funktion wurde verwendet, um die folgenden StackOverflow-Fragen zu beantworten:

Steve Chambers
quelle
7

Sie können es tun ... aber es ist nicht sehr klug ... das ist ungefähr so ​​gewagt, wie ich es versuchen werde ... soweit die vollständige RegEx-Unterstützung Ihre viel bessere Verwendung von Perl oder dergleichen unterstützt.

UPDATE db.tbl
SET column = 
CASE 
WHEN column REGEXP '[[:<:]]WORD_TO_REPLACE[[:>:]]' 
THEN REPLACE(column,'WORD_TO_REPLACE','REPLACEMENT')
END 
WHERE column REGEXP '[[:<:]]WORD_TO_REPLACE[[:>:]]'
Eddie B.
quelle
1
Nein, das wird nicht funktionieren. Stellen Sie sich vor, Ihre Spalte enthält "asdfWORD_TO_REPLACE WORD_TO_REPLACE". Ihre Methode würde zu "asdfREPLACEMENT REPLACEMENT" führen, wobei die richtige Antwort "asdfWORD_TO_REPLACE REPLACEMENT" lautet.
Ryan Shillington
1
@ Ryan ... genau deshalb habe ich gesagt, dass es nicht sehr klug ist ... in dem von Ihnen angegebenen Anwendungsfall würde dies definitiv scheitern. Kurz gesagt, es ist eine schlechte Idee, eine "Regex-ähnliche" Struktur zu verwenden. Noch schlimmer ... wenn Sie die where-Klausel fallen lassen, sind alle Ihre Werte NULL ...
Eddie B
1
Tatsächlich ist Ryan in diesem Fall falsch, da die Markierungen nur Übereinstimmungen für das Wort 'Grenzen' mit der Länge Null finden, sodass nur Wörter mit Grenzen vor und nach dem Wort übereinstimmen würden ... Es ist jedoch immer noch eine schlechte Idee ...
Eddie B
6

Wir können die IF-Bedingung in der SELECT-Abfrage wie folgt verwenden:

Angenommen, für alles mit "ABC", "ABC1", "ABC2", "ABC3", ... möchten wir durch "ABC" ersetzen und dann die Bedingungen REGEXP und IF () in der SELECT-Abfrage verwenden, um dies zu erreichen .

Syntax:

SELECT IF(column_name REGEXP 'ABC[0-9]$','ABC',column_name)
FROM table1 
WHERE column_name LIKE 'ABC%';

Beispiel:

SELECT IF('ABC1' REGEXP 'ABC[0-9]$','ABC','ABC1');
user3796869
quelle
Hallo, danke für den Vorschlag. Ich habe etwas Ähnliches versucht, aber die Leistung meiner Datensätze war unbefriedigend. Bei kleineren Sets kann dies sinnvoll sein.
Piskvor verließ das Gebäude
3

Die folgende findet im Grunde die erste Übereinstimmung von links und ersetzt dann alle Vorkommen davon (getestet in ).

Verwendungszweck:

SELECT REGEX_REPLACE('dis ambiguity', 'dis[[:space:]]*ambiguity', 'disambiguity');

Implementierung:

DELIMITER $$
CREATE FUNCTION REGEX_REPLACE(
  var_original VARCHAR(1000),
  var_pattern VARCHAR(1000),
  var_replacement VARCHAR(1000)
  ) RETURNS
    VARCHAR(1000)
  COMMENT 'Based on https://techras.wordpress.com/2011/06/02/regex-replace-for-mysql/'
BEGIN
  DECLARE var_replaced VARCHAR(1000) DEFAULT var_original;
  DECLARE var_leftmost_match VARCHAR(1000) DEFAULT
    REGEX_CAPTURE_LEFTMOST(var_original, var_pattern);
    WHILE var_leftmost_match IS NOT NULL DO
      IF var_replacement <> var_leftmost_match THEN
        SET var_replaced = REPLACE(var_replaced, var_leftmost_match, var_replacement);
        SET var_leftmost_match = REGEX_CAPTURE_LEFTMOST(var_replaced, var_pattern);
        ELSE
          SET var_leftmost_match = NULL;
        END IF;
      END WHILE;
  RETURN var_replaced;
END $$
DELIMITER ;

DELIMITER $$
CREATE FUNCTION REGEX_CAPTURE_LEFTMOST(
  var_original VARCHAR(1000),
  var_pattern VARCHAR(1000)
  ) RETURNS
    VARCHAR(1000)
  COMMENT '
  Captures the leftmost substring that matches the [var_pattern]
  IN [var_original], OR NULL if no match.
  '
BEGIN
  DECLARE var_temp_l VARCHAR(1000);
  DECLARE var_temp_r VARCHAR(1000);
  DECLARE var_left_trim_index INT;
  DECLARE var_right_trim_index INT;
  SET var_left_trim_index = 1;
  SET var_right_trim_index = 1;
  SET var_temp_l = '';
  SET var_temp_r = '';
  WHILE (CHAR_LENGTH(var_original) >= var_left_trim_index) DO
    SET var_temp_l = LEFT(var_original, var_left_trim_index);
    IF var_temp_l REGEXP var_pattern THEN
      WHILE (CHAR_LENGTH(var_temp_l) >= var_right_trim_index) DO
        SET var_temp_r = RIGHT(var_temp_l, var_right_trim_index);
        IF var_temp_r REGEXP var_pattern THEN
          RETURN var_temp_r;
          END IF;
        SET var_right_trim_index = var_right_trim_index + 1;
        END WHILE;
      END IF;
    SET var_left_trim_index = var_left_trim_index + 1;
    END WHILE;
  RETURN NULL;
END $$
DELIMITER ;
Nae
quelle
3

Ich denke, es gibt einen einfachen Weg, dies zu erreichen, und es funktioniert gut für mich.

Zeilen mit REGEX AUSWÄHLEN

SELECT * FROM `table_name` WHERE `column_name_to_find` REGEXP 'string-to-find'

Zeilen mit REGEX AKTUALISIEREN

UPDATE `table_name` SET column_name_to_find=REGEXP_REPLACE(column_name_to_find, 'string-to-find', 'string-to-replace') WHERE column_name_to_find REGEXP 'string-to-find'

REGEXP-Referenz: https://www.geeksforgeeks.org/mysql-regular-expressions-regexp/

Silambarasan RD
quelle
Danke :) Seit Version 8 ist dies problemlos möglich.
Piskvor hat das Gebäude