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

Quelle est l'alternative à Find_in_set de mysql dans Oracle

Pas une alternative exacte à MySQL FIND_IN_SET , mais dans votre exemple (où vous avez seulement besoin de savoir si une valeur est contenue dans un ensemble séparé par des virgules) Oracle REGEX_COUNT avec la regex '^([^,]+,)*your_value(,[^,]+)*$' conviendra.

Examinez les requêtes SQL suivantes (pour Oracle)...

Exemples avec des chiffres

Rechercher le numéro 1 dans l'ensemble :[1,2,3,4,5,6,11,12,13]

SELECT
    CASE WHEN REGEXP_COUNT('1,2,3,4,5,6,11,12,13', '^([^,]+,)*1(,[^,]+)*$', 1, 'i') > 0
        THEN 1 ELSE 0
    END AS cnt
FROM DUAL;

Renvoie 1 correctement

Rechercher le numéro 1 dans l'ensemble :[111,222,333]. INSTR ne parviendrait pas à signaler un résultat négatif dans ce cas.

SELECT
    CASE WHEN REGEXP_COUNT('111,222,333', '^([^,]+,)*1(,[^,]+)*$', 1, 'i') > 0
        THEN 1 ELSE 0
    END AS cnt
FROM DUAL;

Renvoie 0 correctement

Exemples avec des chaînes

Rechercher 'John' dans un ensemble de noms :

SELECT
    CASE WHEN REGEXP_COUNT('john,peter,jim,kelly,laura,bill,tom,foo,bar', '^([^,]+,)*John(,[^,]+)*$', 1, 'i') > 0
        THEN 1 ELSE 0
    END as cnt
FROM DUAL;

Renvoie 1 correctement

Mais si vous recherchez la lettre 'a' , il renverra correctement zéro (INSTR échouerait à nouveau).

SELECT
    CASE WHEN REGEXP_COUNT('john,peter,jim,kelly,laura,bill,tom,foo,bar', '^([^,]+,)*a(,[^,]+)*$', 1, 'i') > 0
        THEN 1 ELSE 0
    END as cnt
FROM DUAL;

Renvoie 0 correctement

Je sais que cette question a reçu une réponse il y a longtemps, mais elle se classe bien dans les résultats de recherche et pourrait probablement aider les autres qui recherchent une solution simple mais plus correcte que INSTR d'Oracle fonction.

Expressions booléennes

Il est également possible d'utiliser des expressions booléennes, comme OR ou AND .

Un exemple utilisant OR est le suivant :

SELECT
    CASE WHEN REGEXP_COUNT('john,peter,jim,kelly,laura,bill,tom,foo,bar', '^([^,]+,)*(helen|peter)(,[^,]+)*$', 1, 'i') > 0
        THEN 1 ELSE 0
    END as cnt
FROM DUAL;

Renvoie 1 correctement, car il a trouvé "peter" (recherchez soit "helen" ou "pierre" ).

Pour AND l'approche est un peu différente (modifie l'expression CASE au lieu de la regex ):

SELECT
    CASE WHEN
            REGEXP_COUNT('john,peter,jim,kelly,laura,bill,tom,foo,bar', '^([^,]+,)*john(,[^,]+)*$', 1, 'i') > 0 AND
            REGEXP_COUNT('john,peter,jim,kelly,laura,bill,tom,foo,bar', '^([^,]+,)*peter(,[^,]+)*$', 1, 'i') > 0
        THEN 1 ELSE 0
    END as cnt
FROM DUAL;

La requête ci-dessus recherche à la fois "john" ET "Pierre" . Le AND l'opération peut être mise en œuvre facilement en dupliquant le REGEXP_COUNT expression dans le CASE syntaxe, mais en retour avec une petite pénalité de performance.