2010-01-08 3 views
0

je base de données où une colonne contient des nombres. 3 exemples de valeurs:regexp_replace dans la base de données pour inverser une chaîne numérique et insérer un point entre les chiffres

 
1111111555 
2222222555 
3333333555 

dont j'ai besoin de retourner et de mettre un point entre chaque chiffre. c'est-à-dire que le résultat pour chacun des exemples ci-dessus serait:

 
5.5.5.1.1.1.1.1.1.1 
5.5.5.2.2.2.2.2.2.2 
5.5.5.3.3.3.3.3.3.3 

respectivement.

J'ai besoin alors de mettre à jour une autre colonne du résultat. Comment puis-je faire un tel remplacement?

Un test en ligne regexp me donne le résultat que j'ai besoin avec ceci:

 
(\S)(\S)(\S)(\S)(\S)(\S)(\S)(\S)(\S)(\S)/g$10.$9.$8.$7.$6.$5.$4.$3.$2.$1 

mais je ne peux pas l'obtenir pour mettre à jour la base de données avec succès. Des idées comment le faire fonctionner?

+1

Je viens de vérifier: PostgreSQL ne permet qu'un maximum de 9 groupes de capture, donc vous ne pouvez pas utiliser une regex pour cela, semble-t-il. –

+0

Vous avez étiqueté votre question à la fois comme mysql et postgresql. Veuillez indiquer quelle base de données vous utilisez réellement ou si vous avez besoin d'une solution pour les deux. – mikej

+1

J'utiliserai n'importe quelle base de données qui me donnera le résultat. Il peut être mysql postrgesql ou oracle. –

Répondre

1
  1. inverser la chaîne par des moyens classiques (par exemple, une fonction de chaîne intégré)
  2. regex remplacer (\d) avec $1., globalement
  3. supprimer le dernier point du résultat

Plus des regex complexes peuvent vous sauver la dernière étape, par exemple au moyen de look-ahead. Je ne suis pas sûr de ce que votre SGBD de choix supporte ici, donc je l'ai gardé simple.

+2

Juste au cas où il est supporté: remplacer '(\ d) (? = \ D)' par '$ 1.' – Amarghosh

+0

@Amarghosh: PostgreSQL est le seul qui supporte lookahead, donc cela devrait fonctionner. Lookbehind n'est pas supporté, cependant. –

0

Dans Oracle, en supposant que votre valeur de départ est dans une colonne appelée f vous pourriez faire:

substr(regexp_replace(reverse(f), '(\d)', '\1.'), 0, (length(f) * 2) - 1) 

Cette utilise l'approche décrite par Tomalek

Bien sûr, vous pourriez coder en dur 19 en place de (length(f) * 2) - 1 si vous savez que la valeur d'origine va toujours être exactement 10 chiffres.

MySQL a une fonction pour faire expressions rationnelles, mais ne supporte pas la substitution de regexp de sorte que vous devez faire remplacer imbriqué de chaque chiffre 0-9 à son tour. par exemple. pour 1-3:

replace(replace(replace(reverse(f), '3', '3.'), '2', '2.'), '1', '1.') 
+0

Mysql travaille également pour cela avec votre solution, mais les résultats sont étranges s'il y a plus de 10 chiffres: 1.1..1.1.1.1.1.1.1.1.1.1.1. 2.2.2.2.2.2.2.2.2.2. On dirait qu'il ne comprend bien que jusqu'à 9 références, est-il possible d'en utiliser plus? –

+0

Cela semble fonctionner pour moi avec des valeurs plus longues, par ex. sélectionner remplacer (remplacer (remplacer ('11111111111222222222211111111'), '3', '3.'), '2', '2.'), '1', '1.'); donne "1.1.1.1.1.1.1.1.2.2.2.2.2.2.2.2.2.1.1.1.1.1.1.1.1.1.1.1." - Quelle est la valeur avec laquelle vous l'essayez? – mikej

+0

Oui, ça fonctionne très bien. Je n'ai pas compris clairement comment cela fonctionne, et utilisé quelque chose comme .... (REPLACE (REVERSE (number), '12', '12. '),' 11 ', '11.'), ... .. en raison de 2 chiffres, j'ai eu un résultat étrange. Mais maintenant c'est bon. Merci! –

0

Quelque chose comme:

SELECT regexp_replace(reverse(yourcol), E'(\\S)(?=\\S)', E'\\1.', 'g') 

devrait fonctionner. Pour mettre à jour, bien sûr

UPDATE yourtable SET yourcol=regexp_replace(...) 
+0

Il veut aussi inverser - je l'ai manqué aussi bien :( –

+0

Gah. J'ai inversé() là pour cela, j'ai oublié que c'est une fonction personnalisée que j'ai mis dans ma base de données locale: S Pourquoi ne pas nous avoir inversé()? –

2

réponse correcte pour PostgreSQL:

CREATE OR REPLACE FUNCTION reverse_array(ANYARRAY) RETURNS ANYARRAY AS $$ 
    SELECT array((SELECT $1[i] FROM generate_series(array_upper($1, 1), array_lower($1, 1), -1) i)); 
$$ language sql; 

# select array_to_string(
    reverse_array(
     regexp_split_to_array(i, '') 
    ), '.' 
) 
    from (values ('1111111555'), ('2222222555'), ('3333333555')) x (i); 
    array_to_string 
--------------------- 
5.5.5.1.1.1.1.1.1.1 
5.5.5.2.2.2.2.2.2.2 
5.5.5.3.3.3.3.3.3.3 
(3 rows) 
0

J'essaie oracle: SELECT regexp_replace (REVERSE (téléphone), '(\ d)', '\ 1. ') des dossiers

4.3.2.1.1.1.1.1.1.1.1.1.

Cela fonctionne très bien pour moi, même dernier point est utile, je vais y attacher e164.arpa avec concat.Mais ceci est la question suivante.

Merci beaucoup à vous !!

Questions connexes