ORACLE SQL IN子句(SQL查询)

时间:2016-01-20 07:18:26

标签: sql oracle replace

我有:分隔的列1:2:3:。我想把它变成1,2,3。我的查询看起来像,

select name 
from status where id IN (SELECT REPLACE(NEXT_LIST,':',',')
                         FROM status);

但我收到了错误

  

ORA-01722:无效号码

3 个答案:

答案 0 :(得分:2)

(1, 2, 3, 4)('1, 2, 3, 4')不同。 IN需要前者,一系列价值观;你给它后者,一个字符串。

您主要有两种选择:

  1. 动态构建查询,即首先获取列表,然后使用它来构建查询字符串。
  2. 对字符串进行标记。这可以通过自定义流水线函数或递归查询来完成,也可以通过一些XML函数来完成。 Google" Oracle令牌化字符串"找到适合你的方法。
  3. 更新选项#3:在':1:2:3:4:' like '%:3:%'中使用LIKE (这要求你的next_list只包含用冒号分隔的简单数字。没有前导零,没有空格,没有其他字符。)

    select name 
    from status 
    where (select ':' || next_list || ':' from status) like '%:' || id || ':%'
    

答案 1 :(得分:1)

我同意Thorsten,但我想知道我们是否只需再更换一次它会起作用吗?我的意思是这样的:

 select name 
 from status where id IN (SELECT replace(REPLACE(NEXT_LIST,':',','),'''','')
                            FROM status);

答案 2 :(得分:0)

REPLACE函数返回一个字符串,因此嵌套查询返回一个字符串值列表(其中冒号用逗号替换),但不返回数字值列表。当Oracle引擎解释id IN (str_value)时,它会尝试将str_value强制转换为数字并引发异常ORA-01722: invalid number,因为有些情况类似于'1:2:3',这些情况是可定义的不可解析的。

“纯sql”方法使我们使用自定义函数检测数字是否在以冒号分隔的列表中:

-- you need Oracle 12c to use function in the WITH clause
-- on earlier versions just unwrap CASE statement and put it into query
WITH
  FUNCTION in_list(p_id NUMBER, p_list VARCHAR2) RETURN NUMBER DETERMINISTIC IS
  BEGIN
    RETURN CASE WHEN
           instr(':' || p_list || ':', ':' || p_id || ':') > 0        
      THEN 1 ELSE 0 END;
  END;
SELECT *
FROM status 
WHERE in_list(id, next_list) = 1;

这里我假设next_list列中的值是包含用冒号分隔的数字的字符串,没有空格。在通常情况下,您应修改函数以匹配特定的列表格式。