寻找可以用 BULK COLLECT INTO 填充然后用 SELECT 从中选择的数据类型
Looking for a datatype which can be filled with BULK COLLECT INTO and then to be selected from with SELECT
我在使用 PL-SQL 软件包时遇到了很大的问题。
我只想创建一小段代码来执行此操作:
在函数的 IS
部分:
l_tabellen_excl DBMS_utility.name_array;
稍后在代码中:
SELECT DISTINCT TABLE_NAME
BULK COLLECT INTO l_tabellen_excl
FROM
ALL_TAB_COLUMNS
WHERE
TABLE_NAME IN ('TAB_1', 'TAB_2');
最终在 SELECT
语句中使用此变量:
AND col.table_name NOT IN (SELECT * FROM TABLE (l_tabellen_excl))
我在这里得到 ORA-22905: cannot access rows from a non-nested table item
。
我知道我可以只写 AND col.table_name NOT IN ('TAB_1','TAB_2')
但我不想在代码的最深处硬编码...让它很难找到并且更难配置。
我尝试了很多东西:
type array_t is table of varchar2(10);
无效。我收到一条错误消息,提示我无法在 SELECT 语句中使用本地声明的集合。
我试图将变量 i_tabellen_excl
强制转换为本地声明的类型 - 作为一种变通方法。但是我得到 ORA-00902 - 无效数据类型。
我试图声明一个 VARCHAR2,其中包含一个以逗号分隔的字符串 table 列表,它似乎可以工作,但它离干净、编写良好、设计良好的代码还很远。
我尝试了其他不值得一提的选项,比如尝试编写一个函数等
我在这件事上迷路了,任何想法都可以很好地测试。
如果要使用TABLE函数,则必须创建TYPE作为OBJECT 类型,它将把它存储在数据库中并使用它创建一个 function。稍后您可以在 PL/SQL 代码中使用 table 函数。
否则,按照您的做法,使用 NESTED TABLE 您将不得不再次循环以引用集合对象。
SET serveroutput ON
DECLARE
type str_typ
IS
TABLE OF VARCHAR2(200);
str_sub str_typ := str_typ ();
BEGIN
SELECT DISTINCT TABLE_NAME BULK COLLECT INTO str_sub FROM ALL_TAB_COLUMNS;
FOR i IN 1..str_sub.count
LOOP
dbms_output.put_line(str_sub(i));
END LOOP;
END;
/
因此,您不能将其用作数据库对象,为此您必须将类型创建为 对象类型,并创建 table 函数.
例如,
创建类型
SQL> CREATE TYPE col_type AS OBJECT (
2 col_name VARCHAR2(50)
3 );
4 /
Type created.
SQL> CREATE TYPE col_sub_type IS TABLE OF col_type;
2 /
Type created.
构建 table 函数
SQL> CREATE OR REPLACE FUNCTION get_col_tab RETURN col_sub_type AS
2 l_type col_sub_type := col_sub_type();
3 BEGIN
4 FOR i IN (SELECT DISTINCT TABLE_NAME t_name FROM ALL_TAB_COLUMNS) LOOP
5 l_type.extend;
6 l_type(l_type.last) := col_type(i.t_name);
7 END LOOP;
8
9 RETURN l_type;
10 END;
11 /
Function created.
测试一下
SELECT *
FROM TABLE(get_col_tab());
我在使用 PL-SQL 软件包时遇到了很大的问题。
我只想创建一小段代码来执行此操作:
在函数的 IS
部分:
l_tabellen_excl DBMS_utility.name_array;
稍后在代码中:
SELECT DISTINCT TABLE_NAME
BULK COLLECT INTO l_tabellen_excl
FROM
ALL_TAB_COLUMNS
WHERE
TABLE_NAME IN ('TAB_1', 'TAB_2');
最终在 SELECT
语句中使用此变量:
AND col.table_name NOT IN (SELECT * FROM TABLE (l_tabellen_excl))
我在这里得到 ORA-22905: cannot access rows from a non-nested table item
。
我知道我可以只写 AND col.table_name NOT IN ('TAB_1','TAB_2')
但我不想在代码的最深处硬编码...让它很难找到并且更难配置。
我尝试了很多东西:
type array_t is table of varchar2(10);
无效。我收到一条错误消息,提示我无法在 SELECT 语句中使用本地声明的集合。
我试图将变量 i_tabellen_excl
强制转换为本地声明的类型 - 作为一种变通方法。但是我得到 ORA-00902 - 无效数据类型。
我试图声明一个 VARCHAR2,其中包含一个以逗号分隔的字符串 table 列表,它似乎可以工作,但它离干净、编写良好、设计良好的代码还很远。
我尝试了其他不值得一提的选项,比如尝试编写一个函数等
我在这件事上迷路了,任何想法都可以很好地测试。
如果要使用TABLE函数,则必须创建TYPE作为OBJECT 类型,它将把它存储在数据库中并使用它创建一个 function。稍后您可以在 PL/SQL 代码中使用 table 函数。
否则,按照您的做法,使用 NESTED TABLE 您将不得不再次循环以引用集合对象。
SET serveroutput ON
DECLARE
type str_typ
IS
TABLE OF VARCHAR2(200);
str_sub str_typ := str_typ ();
BEGIN
SELECT DISTINCT TABLE_NAME BULK COLLECT INTO str_sub FROM ALL_TAB_COLUMNS;
FOR i IN 1..str_sub.count
LOOP
dbms_output.put_line(str_sub(i));
END LOOP;
END;
/
因此,您不能将其用作数据库对象,为此您必须将类型创建为 对象类型,并创建 table 函数.
例如,
创建类型
SQL> CREATE TYPE col_type AS OBJECT (
2 col_name VARCHAR2(50)
3 );
4 /
Type created.
SQL> CREATE TYPE col_sub_type IS TABLE OF col_type;
2 /
Type created.
构建 table 函数
SQL> CREATE OR REPLACE FUNCTION get_col_tab RETURN col_sub_type AS
2 l_type col_sub_type := col_sub_type();
3 BEGIN
4 FOR i IN (SELECT DISTINCT TABLE_NAME t_name FROM ALL_TAB_COLUMNS) LOOP
5 l_type.extend;
6 l_type(l_type.last) := col_type(i.t_name);
7 END LOOP;
8
9 RETURN l_type;
10 END;
11 /
Function created.
测试一下
SELECT *
FROM TABLE(get_col_tab());