【问题标题】:ORACLE SQL IN Clause (SQL Query)ORACLE SQL IN 子句(SQL 查询)
【发布时间】:2016-04-25 22:16:14
【问题描述】:

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

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

但我遇到了错误

ORA-01722: 无效号码

【问题讨论】:

  • 究竟是哪一列?你能展示一些示例数据吗?
  • 替换函数用于更新字符串的内容,我认为 id 列是数字字段,这就是它给出错误的原因。
  • column next_list 有这样的数据 '2:3:4' 和 id 列有 1,2,3,4 和 name 列有这样的 thamarai, dmitry,raffaello
  • 在ID列中,每一行包含一个数字,对吧?在这种情况下,您的查询是不可能的,因为您检查是否例如“1”“1,2,3” 中。你可以to_char ID ind 将其与LIKE 的语句进行比较
  • 顺便说一句:您对表格的查询也不正确。您当然不会查询表状态以获取 ID,以便再次查询它以获取名称。所以这是一个奇怪的例子。表中的 NEXT_LIST 列是否只有一行?请显示正确的查询。

标签: sql oracle replace


【解决方案1】:

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

你主要有两个选择:

  1. 动态构建查询,即先获取列表,然后使用它构建查询字符串。
  2. 标记字符串。这可以通过自定义流水线函数或递归查询来完成,也可以通过一些 XML 函数来完成。谷歌“Oracle tokenize string”找到适合你的方法。

更新 选项 #3:使用 LIKE,如 ':1:2:3:4:' like '%:3:%' (这要求您的 next_list 仅包含用冒号分隔的简单数字。没有前导零、没有空格、没有其他字符。)

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

【讨论】:

  • 这取决于你的应用是用什么语言编写的。伪代码:list := sqlExecute("SELECT REPLACE(NEXT_LIST,':',',') FROM status"); names := sqlExecute("SELECT name FROM status WHERE id IN (" + list + ")");
【解决方案2】:

我同意 Thorsten 的观点,但我想知道如果我们再更换一次会有效吗?我的意思是这样的:

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

【讨论】:

  • 不,这是行不通的。无论您应用多少字符串操作,这仍然是一个字符串。并且字符串本身不包含引号。引号只是我们需要字符串literal时使用的分隔符。
  • @ThorstenKettner 明白了,谢谢你的解释,看到你在尼斯上面的答案
【解决方案3】:

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 列中的值是包含用冒号分隔的数字的字符串,没有空格。通常情况下,您应该修改函数以匹配特定的列表格式。

【讨论】:

    猜你喜欢
    • 2014-01-02
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多