Propongo esta expresión regular:
^([^2]|[[:<:]][0-9]+/[0-9]+[[:>:]])*([[:<:]]|[a-z])2([[:>:]]|[a-z])([^2]|[[:<:]][0-9]+/[0-9]+[[:>:]])+([[:<:]]|[a-z])2([[:>:]]|[a-z])([^2]|[[:<:]][0-9]+/[0-9]+[[:>:]])*$
Es un poco largo, pero permite más flexibilidad en el sentido de que esas cadenas también se consideran 'válidas':
(2/2) 2new 2new
2new (2/2) 2new (2/2)
En código
SELECT
*
FROM
A
WHERE
description REGEXP '^(([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])*2([[:>:]]|[a-z])){2}([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])*$'
Desglose de expresiones regulares
La expresión regular en realidad usa muchas partes repetitivas, por eso es un poco larga:
^ # Beginning of string
( # Open repeat group
([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])* # Any characters. See #1
2 # 2
([[:>:]]|[a-z]) # Word boundary or alphabet/letter. See #2
){2} # Close repeat group and repeat 2 times
([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])* # Any characters. See #1
$
Desglose detallado
-
#1 ( # Open group [^2]+ # Any characters except 2 | # OR [[:<:]] # Open word boundary [0-9]+ # Any numbers / # Forward slash [0-9]+ # Any numbers [[:>:]] # Close word boundary )* # Close group and repeat any number of times
-
#2 ( # Open group [[:>:]] # Word boundary | # Or [a-z] # Letter/alphabet ) # Close group
Un límite de palabra coincide con el principio y el final de las palabras. La definición de una palabra aquí es una serie de letras, números y caracteres de subrayado.
[[:<:]]
es un límite de palabra de apertura y, por lo tanto, coincide con el comienzo de una palabra.
[[:>:]]
es un límite de palabra de apertura y, por lo tanto, coincide con el final de una palabra.
Su uso aquí asegura que 2
(y las partes numéricas/numéricas) no están rodeadas por otros números (por lo tanto, 21
fallar por ejemplo) o contar un 2
si tienes por ejemplo 21/4
como uno que cuenta para los dos 2
s en la cadena.