Oracle SQL 函数 - 函数调用中的数据类型错误
Oracle SQL function - wrong data type in function call
我的程序包中有一个函数,用于将逗号分隔的 varchar2 输入拆分为行,即。 'one, two, three' 变成:
- 一个
- 两个
- 三个
我已将函数声明为:
function unpack_list(
string_in in varchar2
) return result_str
is
result_rows result_str;
begin
with temp_table as (
SELECT distinct trim(regexp_substr(string_in, '[^,]+', 1, level)) str
FROM (SELECT string_in FROM dual) t
CONNECT BY instr(string_in, ',', 1, level - 1) > 0)
select str bulk collect into result_rows from temp_table;
RETURN result_rows;
end;
和 return 类型为:
type result_str is table of varchar2(100);
但是,像这样调用函数:
select * from unpack_list('one1, two2')
给出以下错误:
ORA-00902: Invalid datatype
知道是什么原因造成的吗?
您正在从 SQL 上下文中调用一个 PL/SQL 函数,该函数 returns 一个 PL/SQL 集合类型(均在您的包中定义)。你不能直接这样做。您可以从 PL/SQL 上下文调用该函数,将结果分配给相同类型的变量,但这不是您尝试使用它的方式。 db<>fiddle 显示你的 set-up,你的错误,它在 PL/SQL 块中工作。
您可以改为在模式级别声明类型,如@Littlefoot 所示:
create type result_str is table of varchar2(100);
并删除包定义,这会发生冲突;适用于 SQL 和 PL/SQL (db<>fiddle)。
或者如果您无法创建 schema-level 类型,您可以使用 built-in 类型:
function unpack_list(
string_in in varchar2
) return sys.odcivarchar2list
is
result_rows sys.odcivarchar2list;
begin
with temp_table as (
SELECT distinct trim(regexp_substr(string_in, '[^,]+', 1, level)) str
FROM (SELECT string_in FROM dual) t
CONNECT BY instr(string_in, ',', 1, level - 1) > 0)
select str bulk collect into result_rows from temp_table;
RETURN result_rows;
end;
也适用于 SQL 和 PL/SQL (db<>fiddle)。
或者您可以使用流水线函数,您的 PL/SQL 集合类型为:
function unpack_list(
string_in in varchar2
) return result_str pipelined
is
begin
for r in (
SELECT distinct trim(regexp_substr(string_in, '[^,]+', 1, level)) str
FROM (SELECT string_in FROM dual) t
CONNECT BY instr(string_in, ',', 1, level - 1) > 0)
loop
pipe row (r.str);
end loop;
RETURN;
end;
适用于 SQL,或适用于 PL/SQL 内的 SQL 运行,但不能直接赋值给集合变量 (db<>fiddle)。
您采用哪种方法取决于您真正需要如何调用该函数。可能存在一些性能差异,但除非重复和密集调用它们,否则您可能不会注意到它们。
前面已经描述了错误的原因,所以我将post另一种可能的解决方案。对于 Oracle 19c(版本 19.7)及更高版本,您可以跳过 table 类型的创建并使用 SQL_MACRO
添加。返回的查询将集成到主查询中。
create function unpack_list (
string_in varchar2
)
return clob
sql_macro(table)
is
begin
return q'[
select distinct
trim(regexp_substr(
unpack_list.string_in,
'[^,]+', 1, level
)) as str
from dual
connect by
instr(
unpack_list.string_in,
',', 1, level - 1
) > 0
]';
end;
/
select *
from unpack_list(
string_in => 'one,two'
)
| STR |
| :-- |
| one |
| two |
db<>fiddle here
我的程序包中有一个函数,用于将逗号分隔的 varchar2 输入拆分为行,即。 'one, two, three' 变成:
- 一个
- 两个
- 三个
我已将函数声明为:
function unpack_list(
string_in in varchar2
) return result_str
is
result_rows result_str;
begin
with temp_table as (
SELECT distinct trim(regexp_substr(string_in, '[^,]+', 1, level)) str
FROM (SELECT string_in FROM dual) t
CONNECT BY instr(string_in, ',', 1, level - 1) > 0)
select str bulk collect into result_rows from temp_table;
RETURN result_rows;
end;
和 return 类型为:
type result_str is table of varchar2(100);
但是,像这样调用函数:
select * from unpack_list('one1, two2')
给出以下错误:
ORA-00902: Invalid datatype
知道是什么原因造成的吗?
您正在从 SQL 上下文中调用一个 PL/SQL 函数,该函数 returns 一个 PL/SQL 集合类型(均在您的包中定义)。你不能直接这样做。您可以从 PL/SQL 上下文调用该函数,将结果分配给相同类型的变量,但这不是您尝试使用它的方式。 db<>fiddle 显示你的 set-up,你的错误,它在 PL/SQL 块中工作。
您可以改为在模式级别声明类型,如@Littlefoot 所示:
create type result_str is table of varchar2(100);
并删除包定义,这会发生冲突;适用于 SQL 和 PL/SQL (db<>fiddle)。
或者如果您无法创建 schema-level 类型,您可以使用 built-in 类型:
function unpack_list(
string_in in varchar2
) return sys.odcivarchar2list
is
result_rows sys.odcivarchar2list;
begin
with temp_table as (
SELECT distinct trim(regexp_substr(string_in, '[^,]+', 1, level)) str
FROM (SELECT string_in FROM dual) t
CONNECT BY instr(string_in, ',', 1, level - 1) > 0)
select str bulk collect into result_rows from temp_table;
RETURN result_rows;
end;
也适用于 SQL 和 PL/SQL (db<>fiddle)。
或者您可以使用流水线函数,您的 PL/SQL 集合类型为:
function unpack_list(
string_in in varchar2
) return result_str pipelined
is
begin
for r in (
SELECT distinct trim(regexp_substr(string_in, '[^,]+', 1, level)) str
FROM (SELECT string_in FROM dual) t
CONNECT BY instr(string_in, ',', 1, level - 1) > 0)
loop
pipe row (r.str);
end loop;
RETURN;
end;
适用于 SQL,或适用于 PL/SQL 内的 SQL 运行,但不能直接赋值给集合变量 (db<>fiddle)。
您采用哪种方法取决于您真正需要如何调用该函数。可能存在一些性能差异,但除非重复和密集调用它们,否则您可能不会注意到它们。
前面已经描述了错误的原因,所以我将post另一种可能的解决方案。对于 Oracle 19c(版本 19.7)及更高版本,您可以跳过 table 类型的创建并使用 SQL_MACRO
添加。返回的查询将集成到主查询中。
create function unpack_list ( string_in varchar2 ) return clob sql_macro(table) is begin return q'[ select distinct trim(regexp_substr( unpack_list.string_in, '[^,]+', 1, level )) as str from dual connect by instr( unpack_list.string_in, ',', 1, level - 1 ) > 0 ]'; end; /
select * from unpack_list( string_in => 'one,two' )
| STR | | :-- | | one | | two |
db<>fiddle here