Неверное количество возвращаемой строки с разделителями-запятыми в предложении IN в Oracle - PullRequest
0 голосов
/ 19 января 2011

Я пытаюсь использовать подзапрос, который возвращает строку с разделителями-запятыми в предложении IN.

Следующий путь:

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) 

И я получаю следующую ошибку:

ORA-01722: неверный номер.

Есть ли лучший способ сделать это или даже возможно?

Ответы [ 2 ]

4 голосов
/ 19 января 2011

Наиболее очевидным объяснением является то, что вы пытаетесь выполнить математику со строкой ...

Попытка преобразования строки символов в число завершилась неудачно, поскольку строка символов не была допустимым числомбуквальный.Только числовые поля или символьные поля, содержащие числовые данные, могут использоваться в арифметических функциях или выражениях.Только числовые поля могут быть добавлены или вычтены из дат.

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

Обновление #1:

Ваше описание меня беспокоит:

Я пытаюсь использовать подзапрос, который возвращает строку с разделителями-запятыми в предложении IN.

Ваш подзапрос должен не возвращать строку с разделителями-запятыми (если g.group_id не является строкой и не ожидает строку с разделителями-запятыми).Вы должны извлекать отдельные элементы в нужном количестве строк (в любом случае, меньше 1000).

Обновление № 2:

Просто чтобы прояснить:

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  

Вы можете сделать это:

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 

Но не это:

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

Поскольку вы не можете сравнить число 1 со строкой '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 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
2 голосов
/ 19 января 2011

Как минимум, чтобы ссылаться на псевдоним GROUP_PATH, вам нужно будет использовать вложенный подзапрос, в котором псевдоним определен, прежде чем ссылаться на него в предложении ORDER BY.Это реально не вызывает ошибку ORA-01722, но это проблема

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) 

Если столбец PERSON_IDS в таблице OTHER представляет собой список значений, разделенных запятыми, ваш список IN не собираетсяделать то, что вы ожидаете.Вам нужно будет преобразовать скалярную строку (в которой есть запятые) в некий набор множественных значений PERSON_ID.Есть разные подходы к этому, у Тома Кайта есть один пример использования переменной IN list .Предполагая, что вы скопируете функцию IN_LIST Тома, вы сможете сделать что-то вроде

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) 
...