Oracle
 sql >> Base de données >  >> RDS >> Oracle

Trouver toutes les correspondances dans un varchar2()

Grande question ! Voici un violon montrant comment interroger les correspondances dans un ensemble de résultats.

Et voici la longue explication au cas où la requête dans le Fiddle n'aurait pas de sens :)

J'utilise une table nommée RegEx_Test avec une colonne MyVal . Voici le contenu du tableau :

MyVal
------------------------------
[A1][abc][B23][D123]a33[bx5]
[Z15][ax0][B0][F13]R3
[X215][A3A][J99]F33F33G24[43][R3]
[Z99][c1][F3][d33]3x24[Y3][f13]
[9a][D41][Q39][XX12]B27[T03][J12]

Votre expression régulière est la suivante :\[[[:alpha:]][[:digit:]]{1,2}\] . C'est la même chose que dans l'autre réponse sauf avec le POSIX :alpha: et :digit: indicateurs, qui sont plus sûrs en cas de jeux de caractères internationaux.

Tout d'abord, vous devez connaître le nombre maximum de correspondances sur n'importe quelle ligne. Utilisez REGEXP_COUNT pour cela :

SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
  FROM Regex_Test

MAX(REGEXP_COUNT(My...
----------------------
                     6

Utilisez ce nombre maximum pour obtenir une table "compteur" (c'est le SELECT ... FROM DUAL ci-dessous) et joignez la table de compteur avec une requête qui extraira vos valeurs en utilisant REGEXP_SUBSTR . REGEXP_SUBSTR a un paramètre "occurrence" et qui utilisera le Counter :

SELECT
  MyVal,
  Counter,
  REGEXP_SUBSTR(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]', 1, Counter) Matched
FROM Regex_Test
CROSS JOIN (
   SELECT LEVEL Counter
   FROM DUAL
   CONNECT BY LEVEL <= (
     SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
     FROM Regex_Test)) Counters

Voici un exemple exécuté sur ma table (résultats partiels) :

MyVal                              Counter Matched
---------------------------------- ------- -------
[9a][D41][Q39][XX12]B27[T03][J12]        1 [D41]
[9a][D41][Q39][XX12]B27[T03][J12]        2 [Q39]
[9a][D41][Q39][XX12]B27[T03][J12]        3 [T03]
[9a][D41][Q39][XX12]B27[T03][J12]        4 [J12]
[9a][D41][Q39][XX12]B27[T03][J12]        5
[9a][D41][Q39][XX12]B27[T03][J12]        6
[A1][abc][B23][D123]a33[bx5]             1 [A1]
[A1][abc][B23][D123]a33[bx5]             2 [B23]
[A1][abc][B23][D123]a33[bx5]             3
... and so on - total is 30 rows

À ce stade, vous avez un ensemble de résultats de correspondances individuelles, plus des valeurs nulles lorsqu'une ligne avait moins que le maximum de correspondances. Les matchs ont toujours leurs parenthèses environnantes. Entourez le tout d'une requête externe qui filtrera les valeurs nulles et supprimera les crochets, et vous aurez votre liste finale :

SELECT SUBSTR(Matched, 2, LENGTH(Matched)-2) FROM (
  SELECT
    MyVal,
    Counter,
    REGEXP_SUBSTR(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]', 1, Counter) Matched
  FROM Regex_Test
  CROSS JOIN (
     SELECT LEVEL Counter
     FROM DUAL
     CONNECT BY LEVEL <= (
       SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
       FROM Regex_Test)) Counters
) WHERE Matched IS NOT NULL

Il s'agit de la requête qui se trouve sur le Fiddle, et elle peut être utilisée dans une autre requête.