sql >> Databasteknik >  >> RDS >> Oracle

Hitta alla matchningar i en varchar2()

Bra fråga! Här är en fiol visar hur man frågar in matchningarna till en resultatuppsättning.

Och här är den långa förklaringen om frågan i fiolen inte är vettig :)

Jag använder en tabell som heter RegEx_Test med kolumnen MyVal . Här är tabellens innehåll:

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]

Ditt regexp genomgående är detta:\[[[:alpha:]][[:digit:]]{1,2}\] . Det är samma som i det andra svaret förutom med POSIX :alpha: och :digit: indikatorer, som är säkrare vid internationella teckenuppsättningar.

Först måste du veta det maximala antalet matchningar på en rad. Använd REGEXP_COUNT för detta:

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

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

Använd det maximala antalet för att få en "räknare"-tabell (det är SELECT ... FROM DUAL nedan) och korskoppla räknartabellen med en fråga som hämtar dina värden med REGEXP_SUBSTR . REGEXP_SUBSTR har en "förekomst"-parameter och som använder 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

Här är ett exempel på min tabell (delresultat):

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

Vid det här laget har du en resultatuppsättning av individuella matchningar, plus nollor där en rad hade mindre än det maximala antalet matchningar. Matcherna har fortfarande sina omgivande parenteser. Omge det hela med en yttre fråga som kommer att filtrera bort nollorna och ta bort parenteserna, och du har din slutliga lista:

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

Det här är frågan som finns på Fiddle, och den kan användas i en annan fråga.



  1. Generera (dvs skriv) en radnummerindexkolumn i MySQL

  2. När behöver jag använda semikolon kontra snedstreck i Oracle SQL?

  3. I node.js mysql-frågan, kontrollera om ingen matchning hittades

  4. Hur man skapar PL/SQL lagrade procedurer utan parametrar i Oracle Database