84 votes

Comment sélectionner une sous-chaîne dans Oracle SQL jusqu'à un caractère spécifique ?

Disons que j'ai une colonne de tableau qui a des résultats comme :

ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore

J'aimerais pouvoir écrire une requête qui sélectionne cette colonne dans ladite table, mais ne renvoie que la sous-chaîne jusqu'au caractère Underscore (_). Par exemple :

ABC
DEFGH
IJKLMNOP

La fonction SUBSTRING ne semble pas être à la hauteur de la tâche car elle est basée sur la position et la position du trait de soulignement varie.

J'ai pensé à la fonction TRIM (plus précisément à la fonction RTRIM) :

SELECT RTRIM('listofchars' FROM somecolumn) 
FROM sometable

Mais je ne sais pas trop comment faire pour que ça marche, puisque ça ne semble supprimer qu'une certaine liste/un certain ensemble de caractères et que je ne cherche que les caractères qui mènent au caractère Underscore.

164voto

OMG Ponies Points 144785

L'utilisation d'une combinaison de SUBSTR, INSTR et NVL (pour les chaînes de caractères sans trait de soulignement) vous permettra d'obtenir ce que vous voulez :

SELECT NVL(SUBSTR('ABC_blah', 0, INSTR('ABC_blah', '_')-1), 'ABC_blah') AS output
  FROM DUAL

Résultat :

output
------
ABC

Utilisez :

SELECT NVL(SUBSTR(t.column, 0, INSTR(t.column, '_')-1), t.column) AS output
  FROM YOUR_TABLE t

Référence :

Addendum

Si vous utilisez Oracle10g+, vous pouvez utiliser regex via REGEXP_SUBSTR .

0 votes

Merci. Très élégant ! (Je n'ai même pas pensé à chercher le support des Regex dans Oracle.

0 votes

Dans Oracle, vous pouvez créer des fonctions (autonomes ou dans un package) et les utiliser dans une instruction select.

9 votes

Échoue si elle est exécutée contre des valeurs qui ne contiennent PAS la sous-chaîne recherchée. instr renvoie 0 si vous avez INSTR('ABC/D', '_') . Au final, vous avez une sous-chaîne de 0 à (0-1) qui est nulle. Ce n'est pas bon.

43voto

user1717270 Points 87

Cela peut être fait en utilisant REGEXP_SUBSTR facilement.

Veuillez utiliser

REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1) 

donde STRING_EXAMPLE est votre chaîne.

Essayez :

SELECT 
REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1) 
from dual

Cela résoudra votre problème.

1 votes

Je vote en faveur de la solution choisie par l'OP car elle est efficace. Cependant, il faut noter que cette solution est beaucoup plus lente que celle de @OMG Ponies, surtout si elle est utilisée dans des conditions où. Mes tests ont montré que l'exécution d'une requête identique est environ 6 fois plus lente. Cette question va encore plus loin sur le sujet stackoverflow.com/questions/41156391/

0 votes

Dans mes tests, la INSTR fonctionne à peu près aussi rapidement que la solution REGEXP solution.

7voto

Rajesh Chamarthi Points 8847

Vous devez obtenir la position du premier soulignement (en utilisant INSTR) et ensuite obtenir la partie de la chaîne de caractères du premier soulignement à (pos-1) en utilisant substr.

  1  select 'ABC_blahblahblah' test_string,
  2         instr('ABC_blahblahblah','_',1,1) position_underscore,
  3         substr('ABC_blahblahblah',1,instr('ABC_blahblahblah','_',1,1)-1) result
  4*   from dual
SQL> /

TEST_STRING      POSITION_UNDERSCORE RES
---------------- ------------------  ---
ABC_blahblahblah                  4  ABC

Documentation de l'Instr

Documentation du Susbtr

2voto

EvilTeach Points 12235

Une autre possibilité serait d'utiliser REGEXP_SUBSTR.

-2voto

Shadi Mahasneh Points 1

Bien que la combinaison substr,instr soit une bien meilleure idée, plus facile et plus performante, il n'est pas inutile de savoir comment utiliser la fonction rtim pour obtenir un tel résultat.

Ce dont vous avez besoin ici, c'est d'une fonction rtim imbriquée, de sorte que la "rtrim" interne supprime tout ce qui se trouve après le symbole _, bien sûr, pour ce faire, vous devrez fournir à la "rtrim" tous les caractères possibles dans la chaîne, puis la "rtim" externe vient supprimer le symbole _.

La solution ressemblerait donc à ceci :

SELECT RTRIM ( RTRIM ('ABC_blahblahblah', ' abcdefghijklmnopqrstuvwxyz0123456789 \-!\&\<\>#+.,;/$?'' \\t') , '_' ) FROM dual ;

Et pour ce qui est de votre code, je serai.. :

SELECT RTRIM ( RTRIM (t.column , 'set of chars could possibly follow the _ symbol') , '_' ) FROM YOUR_TABLE t ;

salutations

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X