Rolf B: RegEx mysql 8

Beitrag lesen

Hallo Jörg,

Frage vorweg: Bist Du absolut sicher, dass Du MYSQL 8 hast und kein Datenmariechen? MYSQL 8 soll teuer sein, hab ich gehört, weswegen die Hoster alle zur Maria geflüchtet sind.

Wenn's MYSQL 8 ist: RTFM.

MySQL implements regular expression support using International Components for Unicode (ICU), which provides full Unicode support and is multibyte safe. (Prior to MySQL 8.0.4, MySQL used Henry Spencer's implementation of regular expressions, which operates in byte-wise fashion and is not multibyte safe.

und etwas später:

The Spencer library supports word-beginning and word-end boundary markers ([[:<:]] and [[:>:]] notation). ICU does not. For ICU, you can use \b to match word boundaries; double the backslash because MySQL interprets it as the escape character within strings.

Fettsatz von mir. Leider steht im MYSQL Artikel nicht, welche Backslash-Sequenzen ICU unterstützt. \b ist bekannt als Word Boundary Marker, ja, aber ob ICU das ganze PCRE-Spektrum abdeckt - das steht da nicht. Im Zweifelsfall muss man probieren oder die ICU-Regex Doku studieren.

Allerdings wird die Word Boundary-Lösung immer noch Peter in "Rudi,Hans Peter,Otto" finden. D.h. deine Lösung war schon in 5.7 falsch. Du musst anders suchen.

FIND_IN_SET ist meiner Meinung nach keine Lösung. Es erfordert, dass die User-Spalte vom Typ SET ist. Ist sie das? SET Spalten haben eine Einschränkung:

A SET column can have a maximum of 64 distinct members.

Ist das okay für Dich? Ich GLAUBE nämlich, dass das bedeutet, dass es maximal 64 verschiedene Usernamen in der gesamten Tabelle geben darf, weil MYSQL jedem Namen eine Bitposition zuordnet.

Anderes Problem: Was ist mit User-Einträgen wie "Rolf, Joerg , Fritz,Otto,Paul" - also unklare Spacemengen um das Komma herum. Kann das passieren? Haben User durch Fehlbedienung die Möglichkeit, kreativ Spaces einzusetzen?

Eigentlich müsstest Du nach einer Sequenz dieser Art suchen:

  • ^ oder ,
  • Whitespace
  • gesuchter name
  • Whitespace
  • , oder $

Die Sache mit dem Whitespace ist optional, das hängt von deinen Daten ab. Frage ist dann auch, ob Du nur das Space (\x20) berücksichtigen musst oder auch das &nbsp (\xA0), ein Tab (\x09) oder die Flut von Unicode-Whitespacevarianten. Ich hoffe für Dich, dass Du einfach gar keine Spaces um deine Kommas herum hast.

In dem Fall sähe eine brauchbare Regex meiner Meinung nach so aus:

(^|,)Joerg(,|$)

Man muss das mit dem |-Ausdruck machen, weil die Start- und Ende-Assertions ^ und $ nicht in einem Zeichenklassen-Ausdruck (also eckige Klammern) zulässig sind.

Simple Spaces kannst Du noch so ergänzen:

(^|,) *Joerg *(,|$)

Generisches Whitespace müsste so gehen:

(^|,)[[:blank:]]*Joerg[[:blank:]]*(,|$)

Dass dieses geregexe eine Performance-Katastrophe ist, brauch ich Dir nicht zu sagen. Wenn ich dein Posting so lese, weißt Du das schon... Ich hoffe, deine Query enthält weitere Suchbedingungen, die die zu durchsuchende Menge begrenzen, so dass nicht allzuviele Rows durchforstet werden müssen. Wenn die User-Spalte im Index ist, könnte das aber dazu führen, dass er mit einem Index-Scan arbeiten kann und keinen Table-Scan braucht. Hängt jetzt von der Gesamtquery ab. Mach einen EXPLAIN.

Woher ich das weiß? Hab ich in meinem Leben schonmal MYSQL 8 benutzt? Nö. Kenn ich die ICU Library? Nö. Alles just im Handbuch zusammengelesen. Mag also falsch sein. In dem Fall findest Du den Link für weitere Lektüre zu Beginn meiner Antwort.

Rolf

--
sumpsi - posui - obstruxi