2011-01-19 2 views
0

J'essaie d'utiliser une sous-requête qui renvoie une chaîne délimitée par des virgules dans une clause IN.Nombre invalide de chaînes séparées par des virgules dans une clause IN dans Oracle

de la manière suivante:

SELECT p.person_id, g.name || '>>' || p.firstname || ' ' || p.lastname as GROUP_PATH 
FROM PERSON p 
LEFT JOIN GROUP g ON (
    g.group_id = p.group_id 
) 
WHERE p.person_id IN ( 
    SELECT person_ids FROM other WHERE other_id = :OTHER_ID 
) 
ORDER BY lower(GROUP_PATH) 

Et je reçois l'erreur suivante:

ORA-01722: invalid number.

Y at-il une meilleure façon de faire ceci ou même possible?

+0

Pouvez-vous afficher la définition de la table (en particulier les types de colonnes ID) pour les trois tables; et comment ': other_id' est défini?Il se peut que vous joigniez une colonne numérique à un varchar dont vous pensez qu'il ne contient que des nombres, ou seulement des correspondances sur des nombres, et que ce soit sur une valeur non numérique que vous ne pensez pas être pertinente. –

+0

Je viens de remarquer que ma requête initiale était erronée. Je l'ai mis à jour. – Kel

+0

Est-ce que 'person_ids' dans' other' est une liste séparée par des virgules? Si c'est le cas, cela ne fonctionnera pas dans une clause "IN". Vous devez analyser la chaîne dans une collection et utiliser la collection dans la requête. Mais vous ne devriez jamais stocker une liste de clés séparées par des virgules dans une base de données relationnelle, vous devez donc probablement corriger votre modèle de données. –

Répondre

4

L'explication la plus évidente est que vous essayez de faire des maths avec une chaîne ...

The attempted conversion of a character string to a number failed because the character string was not a valid numeric literal. Only numeric fields or character fields containing numeric data may be used in arithmetic functions or expressions. Only numeric fields may be added to or subtracted from dates.

http://ora-01722.ora-code.com/

Mise à jour # 1:

Votre description me préoccupe:

I am trying to use a subquery that returns a comma delimited string in a IN clause.

Y notre sous-requête doit pas renvoyer une chaîne délimitée par des virgules (sauf si g.group_id est une chaîne et attend une chaîne délimitée par des virgules). Vous devez récupérer les éléments individuels en autant de lignes que nécessaire (moins de 1 000 de toute façon).

Mise à jour # 2:

Juste pour préciser:

SELECT * 
FROM (
    SELECT 1 AS FOO_ID FROM DUAL UNION SELECT 2 FROM DUAL UNION SELECT 3 FROM DUAL 
) FOO; 

FOO_ID     
---------------------- 
1      
2      
3 

Vous pouvez faire ceci:

SELECT * 
FROM (
    SELECT 1 AS FOO_ID FROM DUAL UNION SELECT 2 FROM DUAL UNION SELECT 3 FROM DUAL 
) FOO 
WHERE FOO_ID IN (1, 2); 

FOO_ID     
---------------------- 
1      
2 

Mais pas:

SELECT * 
FROM (
    SELECT 1 AS FOO_ID FROM DUAL UNION SELECT 2 FROM DUAL UNION SELECT 3 FROM DUAL 
) FOO 
WHERE FOO_ID IN ('1,2'); 

SQL Error: ORA-01722: invalid number 

Parce que vous ne pouvez pas comparer le numéro 1 avec la chaîne '1,2'. Les sous-requêtes suivent des règles similaires:

SELECT * 
FROM (
    SELECT 1 AS FOO_ID FROM DUAL UNION SELECT 2 FROM DUAL UNION SELECT 3 FROM DUAL 
) FOO 
WHERE FOO_ID IN (
    SELECT 1 AS FOO_ID FROM DUAL UNION SELECT 2 FROM DUAL 
); 

FOO_ID     
---------------------- 
1      
2 

SELECT * 
FROM (
    SELECT 1 AS FOO_ID FROM DUAL UNION SELECT 2 FROM DUAL UNION SELECT 3 FROM DUAL 
) FOO 
WHERE FOO_ID IN (
    SELECT '1,2' AS FOO_ID FROM DUAL 
); 

SQL Error: ORA-01722: invalid number 
+0

Lorsque je n'interroge que la sous-requête et que je colle les résultats (délimités par des virgules) dans la clause IN, cela fonctionne correctement. Une explication pour cela? – Kel

+1

Disons que vous obtenez «10, 20,30». Qu'est ce que tu fais avec? 'g.group_id IN (10,20,30)' (trois chiffres) ou 'g.group_id IN ('10, 20,30 ')' (une chaîne)? –

+0

J'ai remarqué que j'ai réécrit la requête erronée. Vérifiez-le maintenant. Je suis supposé avoir plusieurs person_ids et non group_ids. – Kel

2

Au minimum, afin de faire référence à l'alias GROUP_PATH, vous devez avoir besoin d'utiliser un sous-requête imbriquée où l'alias est défini avant vous faites référence dans votre clause ORDER BY. C'est réaliste pas responsable de l'erreur ORA-01722, mais il est un problème

SELECT group_id, group_path 
    FROM (SELECT g.group_id, 
       g.name || '>>' || p.firstname || ' ' || p.lastname as GROUP_PATH 
      FROM PERSON p 
       LEFT JOIN GROUP g ON (
         g.group_id = p.group_id 
       ) 
     WHERE p.person_id IN ( 
       SELECT person_ids FROM other WHERE other_id = :OTHER_ID 
       ) 
ORDER BY lower(GROUP_PATH) 

Si la colonne PERSON_IDS dans le tableau OTHER est une liste séparée par des virgules des valeurs, votre liste IN ne va pas faire ce que vous attendre. Vous devez transformer la chaîne scalaire (qui contient des virgules) en une sorte de collection de plusieurs valeurs PERSON_ID. Tom Kyte a un exemple d'utilisation d'un variable IN list. En supposant que vous copiez la fonction IN_LIST de Tom, vous devriez être capable de faire quelque chose comme

SELECT group_id, group_path 
    FROM (SELECT g.group_id, 
       g.name || '>>' || p.firstname || ' ' || p.lastname as GROUP_PATH 
      FROM PERSON p 
       LEFT JOIN GROUP g ON (
         g.group_id = p.group_id 
       ) 
     WHERE p.person_id IN ( 
       SELECT column_value 
       FROM TABLE(SELECT in_list(person_ids) 
           FROM other 
          WHERE other_id = :OTHER_ID) 
       ) 
ORDER BY lower(GROUP_PATH) 
+0

Merci pour votre réponse Justin. Je viens de remarquer que j'ai mal écrit la requête. Au lieu d'obtenir une chaîne délimitée par des virgules d'identifiants de groupes, j'obtiens des identifiants de personnes délimités par des virgules. – Kel

+0

@Kel - Modifié mes requêtes pour correspondre –

Questions connexes