函数返回varchar里面选择

时间:2018-04-04 13:49:23

标签: plsql oracle11g

尝试概括SQL将字符串/ varchar拆分为记录的内容。这是工作SQL:

SELECT test.* FROM test JOIN (
SELECT level nbr, REGEXP_SUBSTR('1,3', '(.*?)(,|$)', 1, level, NULL, 1) value
FROM dual CONNECT BY level <= REGEXP_COUNT('1,3', ',')+1 ORDER BY level
) requested ON test.id=requested.value

我的意思是概括;将重复的SQL(在这种情况下,括号中的位从上面的工作SQL中移动)移动到过程/函数,以便可以重用它。在这种情况下,我试图找到一种方法来插入生成的内部select语句。这就是通用SQL的外观:

SELECT t.* FROM table t JOIN (<GENERATED_INNER_SELECT>) my ON t.x=my.x;

但是我还没有成功,我试过但是调用我的函数生成内部select语句直接导致:

  

ORA-00900:无效的SQL语句

使用通用SQL中的函数导致:

  

ORA-00907:缺少右括号

在这种情况下,这些错误都不会对我有任何意义。

也许你可以帮忙吗? check out the full case on dbfiddle

1 个答案:

答案 0 :(得分:4)

如果生成要用作子查询的SQL片段,那么将其作为子查询嵌入的整体语句也必须动态执行。

让函数实际执行拆分并返回集合 - 作为模式级集合类型会更简单:

CREATE TYPE T_NUMBERS AS TABLE OF NUMBER
/

CREATE OR REPLACE FUNCTION split(p_string VARCHAR2, p_seperator VARCHAR2 DEFAULT ',')
    RETURN T_NUMBERS AS
    L_NUMBERS T_NUMBERS;
BEGIN
    SELECT REGEXP_SUBSTR(p_string, '(.*?)(,|$)', 1, level, NULL, 1)
    BULK COLLECT INTO L_NUMBERS
    FROM dual
    CONNECT BY level <= REGEXP_COUNT(p_string, ',')+1;

    RETURN L_NUMBERS;
END split;
/

SELECT * FROM TEST
WHERE id MEMBER OF (split('1,3'))
/

        ID NAM
---------- ---
         1 foo
         3 foe

或者如果您更喜欢表集合表达式方法:

SELECT t.*
FROM TABLE(split('1,3')) tmp
JOIN test t ON t.id = tmp.column_value;

如果可以首先使用一组数字调用查询,但是如果没有看到调用是如何进行的 - 并且生成的字符串 - 很难准确地说出你是怎么回事,那就更简单了#39;需要改变它。您甚至可以使用内置集合类型,而不必定义自己的集合类型:

SELECT t.*
FROM TABLE(SYS.ODCINUMBERLIST(1,3)) tmp
JOIN test t ON t.id = tmp.column_value;

但它依赖于调用者能够传递数字而不是字符串(注意缺少单引号...)