Eu proponho este regex:
^([^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]+[[:>:]])*$
É um pouco longo, mas permite um pouco mais de flexibilidade, pois essas strings também são consideradas 'válidas':
(2/2) 2new 2new
2new (2/2) 2new (2/2)
No código
SELECT
*
FROM
A
WHERE
description REGEXP '^(([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])*2([[:>:]]|[a-z])){2}([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])*$'
SQLFiddle
Detalhamento de Regex
O regex realmente usa muitas partes repetidas, então é por isso que é um pouco longo:
^ # 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
$
Divisão detalhada
-
Nº 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
Um limite de palavra corresponde ao início e ao fim das palavras. A definição de uma palavra aqui é uma série de alfabeto, números e caracteres de sublinhado.
[[:<:]]
é um limite de palavra de abertura e, portanto, corresponde ao início de uma palavra. [[:>:]]
é um limite de palavra de abertura e, portanto, corresponde ao final de uma palavra. Seu uso aqui garante que
2
(e as partes numéricas/numéricas) não são cercadas por outros números (portanto, faz 21
falhar por exemplo) ou contar um 2
se você tiver, por exemplo, 21/4
como um que conta para os dois 2
s na cadeia.