web-dev-qa-db-fra.com

Émuler Regexp comme comportement dans DB2 SQL

J'ai posté la même chose sur Stackoverflow (s'il vous plaît, faites-moi savoir si je dois supprimer un).

Je travaille sur une base de données DB2 et aussi loin que je peux voir que RegexP n'est pas pris en charge (sans bibliothèques supplémentaires).

Donc, je ne peux pas mettre en œuvre quelque chose de similaire à ce qui est expliqué dans cet article " apportant la puissance de l'expression régulière correspondant à SQL "

Savez-vous si je peux "émuler", avec une déclaration SQL, une expression régulière comme celle-ci?

^ a [aofdmep] {1} [A-Z] {1} [A-Z0-9] {4} [sidbfkfpo] {1}

Edit

Dans l'hypothèse ci-dessus, j'ai trouvé que c'est acceptable pour mon cas A [~ # ~] où [~ # ~] Comme prédicat:

Où user_name pas comme 'a_______'

Mais c'est un dangereux et ne couvre pas les autres cas où je n'ai pas de caractères fixes que je peux correspondre.

7
tmow

Tout d'abord, le {1}s sont redondants, donc c'est vraiment juste:

^[aofdmep][a-z][a-z0-9]{4}a[sidbfkfpo]

C'est en fait un jeu assez simple ... il suffit de regarder ce que les 8 premiers caractères de la chaîne sont, et c'est toujours une chaîne de longueur fixe, vous permettant ainsi de construire une table de toutes les permutations, puis de faire:

WHERE SUBSTR(string_to_match, 1, 8) IN (
  SELECT valid_prefixes FROM table_of_things_to_match
)

Malheureusement, il est 7 * 26 * 36 ^ 4 * 9 ... 2,75 milliards de combinaisons possibles, mais toujours, des chaînes fixes, vous pourriez donc faire:

WHERE SUBSTR(string_to_match, 1, 1) IN ('a','o','f','d','m','e','p')
  AND SUBSTR(string_to_match, 2, 1) IN ('a','b','c','d' ... 'z')
  AND SUBSTR(string_to_match, 3, 1) IN ('a','b','c','d' ... 'z','0','1' ... '9')
  AND SUBSTR(string_to_match, 4, 1) IN ('a','b','c','d' ... 'z','0','1' ... '9')
  AND SUBSTR(string_to_match, 5, 1) IN ('a','b','c','d' ... 'z','0','1' ... '9')
  AND SUBSTR(string_to_match, 6, 1) IN ('a','b','c','d' ... 'z','0','1' ... '9')
  AND SUBSTR(string_to_match, 7, 1) = 'a'
  AND SUBSTR(string_to_match, 8, 1) IN ('s','i','d','b','f','k','p','o')

(remplissez le ... bits, bien sûr)

oups, il y a deux fs dans ce dernier cours de caractère, il n'y a donc que 2,45 milliards de permutations.

Je ne vais pas prétendre que ça va être rapide ... ça ne sera probablement pas, mais ça va vous chercher le modèle que vous recherchez. Si vous avez tendance à faire cela beaucoup, je construirais probablement une table de caractères afin que vous ayez eu un moyen facile de sélectionner alpha/numérique ou alphanumérique.

11
Joe

Depuis que cette ancienne question a été creusée de toute façon, je mentionnerai que vous pouvez utiliser le support XQuery intégré à DB2 pour une correspondance d'expression régulière, quelque chose du long des lignes de

select whatever
from users
where
   xmlcast(
     xmlquery('fn:matches($USER_NAME,"^a[aofdmep][a-z][a-z0-9]{4}[sidbfkfpo]")') 
     as integer) = 1

XMLQUERY ci-dessus appelle la fonction XQuery matches Contre la colonne USER_NAME. Le résultat est un XML boolean, donc le XMLCAST est utilisé pour la convertir en un type de données SQL.

11
mustaccio
SELECT * FROM
   (SELECT 'afr923zs' MyString FROM SYSIBM.SYSDUMMY1)
WHERE substr(MyString,1,1) = 'a' 
AND   substr(MyString,2,1) IN ('a','o','f','d','m','e','p')
AND   substr(MyString,3,1) BETWEEN 'a' AND 'z'
AND  (substr(MyString,4,1) BETWEEN 'a' AND 'z' 
   OR substr(MyString,4,1) BETWEEN '0' AND '9')
AND  (substr(MyString,5,1) BETWEEN 'a' AND 'z' 
   OR substr(MyString,5,1) BETWEEN '0' AND '9')
AND  (substr(MyString,6,1) BETWEEN 'a' AND 'z' 
   OR substr(MyString,6,1) BETWEEN '0' AND '9')
AND  (substr(MyString,7,1) BETWEEN 'a' AND 'z' 
   OR substr(MyString,7,1) BETWEEN '0' AND '9')
AND   substr(MyString,8,1) IN ('s','i','d','b','f','k','p','o');
6
Leigh Riffel

Regexp_ike est maintenant disponible dans DB2 pour Iseries - voir: http://www.itjungle.com/fhg/fhg051915-story01.html

2
mikrom

Dans DB2 pour z/OS, le SQL inclurait le passage comme suit

select whatever
from users
where
   xmlcast(
     xmlquery('fn:matches($USER_NAME,"^a[aofdmep][a-z][a-z0-9]{4}[sidbfkfpo]")'
      PASSING USER as "USER_NAME") 
     as integer) = 1
0
Aidanh