Plsql 函数返回select中的varchar

Plsql 函数返回select中的varchar,plsql,oracle11g,Plsql,Oracle11g,试图概括将字符串/varchar拆分为记录的SQL语句。以下是工作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=reque

试图概括将字符串/varchar拆分为记录的SQL语句。以下是工作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;
但是我还没有成功,我尝试了tho,但是调用我的函数来生成内部select语句直接导致:

ORA-00900:无效的SQL语句

在通用SQL中使用函数会导致:

ORA-00907:缺少右括号

在这种情况下,这些错误对我来说毫无意义


也许你能帮忙

如果生成一个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(SYS.ODCINUMBERLIST(1,3)) tmp
JOIN test t ON t.id = tmp.column_value;

但是它依赖于调用方能够传递数字而不是字符串。注意,缺少单引号…

如果生成一个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(SYS.ODCINUMBERLIST(1,3)) tmp
JOIN test t ON t.id = tmp.column_value;

但是它依赖于调用方能够传递数字而不是字符串。注意,缺少单引号…

除非整个语句是动态执行的,否则无法使用生成的内部select。您真正想要做的是在测试中查找ID位于逗号分隔字符串中的行,对吗?那根绳子是从哪里来的?我有一部分想知道,不管怎么说,它是否可以作为一个集合来提供…@AlexPoole是的,这是正确的。字符串来自一个隐藏字段,该字段根据检查的行收集id。也许有一种方法可以通过PL/SQL代码而不是SQL查询来完成此操作?@Fleuv您可以定义一个提取数据的视图,然后在SQL语句中使用它?或者,您可以创建一个函数,返回在数据库级别定义的嵌套表数组,然后从中进行选择,例如select*from tablesome\U function\U returning\U nested\U table。就我个人而言,我认为视图是更好的方法,但是YMMV。除非整个语句是动态执行的,否则不能使用生成的内部select。您真正想要做的是在测试中查找ID位于逗号分隔字符串中的行,对吗?那根绳子是从哪里来的?我有一部分想知道,不管怎么说,它是否可以作为一个集合来提供…@AlexPoole是的,这是正确的。字符串来自一个隐藏字段,该字段根据检查的行收集id。也许有一种方法可以通过PL/SQL代码而不是SQL查询来完成此操作?@Fleuv您可以定义一个提取数据的视图,然后在SQL语句中使用它?或者,您可以创建一个函数,返回在数据库级别定义的嵌套表数组,然后从中进行选择,例如select*from tablesome\U function\U returning\U nested\U table。就我个人而言,我认为观点是更好的方法,但是YMMV。