Oracle COLLECT 函数和类型
我在 Oracle 10g 和 COLLECT
函数的使用方面遇到问题。我今天早上才发现它的存在,但有一个问题可以通过将它与 member of
条件结合使用来解决。
最初,我编写了如下所示的代码,该代码返回错误“ORA_00932:不一致的数据类型:预期的 UDT 得到 -”。
with my_tab as (
select 1 as cola, 1 as colb from dual union all
select 1 as cola, 2 as colb from dual union all
select 2 as cola, 3 as colb from dual union all
select 2 as cola, 4 as colb from dual union all
select 3 as cola, 3 as colb from dual union all
select 3 as cola, 4 as colb from dual union all
select 4 as cola, 1 as colb from dual union all
select 4 as cola, 2 as colb from dual
)
select
cola,
colb_vals
from (
select
cola,
collect(colb) as colb_vals
from my_tab
group by cola
)
where 2 member of colb_vals
我发现这有点奇怪,因为在 Oracle 10.2.4.0 中,数据库似乎会创建一个临时的系统生成的用户定义类型,并使用它。如果我删除条件(where 2 member of colb_vals
),则代码将运行并显示检索到的数据,其中包括临时 UDT(名为 SYSTPblahblahblah==)。
经过更多搜索后,我意识到可以使用 CREATE TYPE
解决此问题,然后使用 CAST
函数更改嵌套表的类型。这有效。
这是使用 CREATE TYPE number_ntt as TABLE OF NUMBER;
并将 collect(colb)
替换为 cast(collect(colb) as number_ntt)
然后我尝试使用在包中创建的嵌套表类型,因为我只需要此类型可用于单个包中的一个过程中的一个特定查询。我无法让它发挥作用。
create or replace package mike_temp_pkg as
type number_ntt is table of number;
end mike_temp_pkg;
这次将 collect(colb)
替换为 cast(collect(colb) as mike_temp_pkg.number_ntt)
这导致了 ORA-00932: invalid datatype。
所以我的问题实际上分为两部分:
为什么系统生成用户 定义类型适用于
select
但不适用于member of
?为什么类型需要是 SQL 类型而不是 PL/SQL 类型 包裹?我并没有真正定义类型 经常这样,所以可能有一个 这个问题的简单答案。
I've got an issue with Oracle 10g and the use of the COLLECT
function. I only found out about its existence this morning but have a problem which could be solved by using it in association with the member of
condition.
Initially I wrote the code shown below, which came back with the error "ORA_00932: inconsistent datatypes: expected UDT got -".
with my_tab as (
select 1 as cola, 1 as colb from dual union all
select 1 as cola, 2 as colb from dual union all
select 2 as cola, 3 as colb from dual union all
select 2 as cola, 4 as colb from dual union all
select 3 as cola, 3 as colb from dual union all
select 3 as cola, 4 as colb from dual union all
select 4 as cola, 1 as colb from dual union all
select 4 as cola, 2 as colb from dual
)
select
cola,
colb_vals
from (
select
cola,
collect(colb) as colb_vals
from my_tab
group by cola
)
where 2 member of colb_vals
I found this a little strange since in Oracle 10.2.4.0, it seems that the database will create a temporary system generated user defined type, and use that. If I remove the condition, (where 2 member of colb_vals
) then the code will run and show the data retrieved included the temporary UDT (named SYSTPblahblahblah==).
After a bit more searching, I realised that I could solve this be using CREATE TYPE
and then using the CAST
function to change the type of the nested table. Which worked.
This was using CREATE TYPE number_ntt as TABLE OF NUMBER;
and replacing collect(colb)
with cast(collect(colb) as number_ntt)
I then tried to use a nested table type created in a package, since I only need this type to be available for one particular query in one procedure in a single package. And I couldn't get it to work.
create or replace package mike_temp_pkg as
type number_ntt is table of number;
end mike_temp_pkg;
And this time replacing collect(colb)
with cast(collect(colb) as mike_temp_pkg.number_ntt)
This resulted in ORA-00932: invalid datatype.
So the question I have is in two parts really:
Why does the system generated user
defined type work for theselect
but not for themember of
?Why does the type need to be a SQL
type and not a PL/SQL type in a
package? I don't really define types
that often so there might be a
simple answer to that question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
(1)
COLLECT 函数文档指出“要获取此函数的结果,您必须在 CAST 函数中使用它”。我怀疑它根本不被设计为支持任何用途,除了其内容的简单转储之外,除非您将其转换为定义的类型。
(2)
SQL 解析器不知道或无法访问 PL/SQL 块中定义的类型。即使当您在 PL/SQL 代码内部执行 SQL 语句时,该语句本质上也会被传递给独立的解析器(PL/SQL 变量名称被绑定变量占位符替换)。
(1)
The COLLECT function documentation states "To get the results of this function you must use it within a CAST function." I suspect it simply is not designed to support any uses, except a simple dump of its contents, unless you cast it to a defined type.
(2)
The SQL parser has no knowledge of or access to types defined in PL/SQL blocks. Even when you execute a SQL statement inside of PL/SQL code, the statement is essentially handed off to an independent parser (with PL/SQL variable names replaced by bind variable placeholders).