使用 Table 集合表达式从关联数组中选择问题
Issue selecting from Associative Array using a Table Collection Expression
我似乎在使用关联数组中的 Table 集合表达式到 select 时遇到问题(注意:我使用的是 Oracle 12c,所以这是允许的:Oracle Documentation)
举下面这个“简单”的例子:
首先,创建一个声明记录和关联数组的包:
CREATE OR REPLACE PACKAGE table_test
IS
TYPE pt_DateSpan IS RECORD
(
StartDate DATE,
EndDate DATE
);
TYPE pt_DateSpanTable IS TABLE OF pt_DateSpan INDEX BY PLS_INTEGER;
END;
/
然后,我编写了以下匿名块来测试功能:
DECLARE
l_tTest table_test.pt_DateSpanTable;
PROCEDURE lp_outputAArray (p_aaInput table_test.pt_DateSpanTable) IS
l_nTableSize INTEGER;
BEGIN
--I know I can use p_aaInput.COUNT, but I want to select using TABLE() to show that the functionality "works"
SELECT COUNT(*)
INTO l_nTableSize
FROM TABLE(p_aaInput);
dbms_output.put_line('Table Size: '||l_nTableSize);
FOR i IN 1..p_aaInput.COUNT LOOP
dbms_output.put_line(i||': '||to_char(p_aaInput(i).StartDate, 'MM/DD/YYYY')||' - '||to_char(p_aaInput(i).EndDate, 'MM/DD/YYYY'));
END LOOP;
END lp_outputAArray;
BEGIN
--ADD RECORD TO ASSOCIATIVE ARRAY
SELECT to_date('01/01/2000', 'MM/DD/YYYY'), to_date('01/01/2010', 'MM/DD/YYYY')
BULK COLLECT INTO l_tTest
FROM DUAL;
lp_outputAArray(l_tTest);
--SELECT THE ASSOCIATIVE ARRAY INTO ITSELF
SELECT t.StartDate, t.EndDate
BULK COLLECT INTO l_tTest
FROM TABLE(l_tTest) t;
lp_outputAArray(l_tTest);
END;
/
此块产生以下输出:
Table Size: 1
1: 01/01/2000 - 01/01/2010
Table Size: 0
我的问题是为什么第二个输出与第一个不一样?
另外,我意识到我不需要在这个例子的大部分中使用 BULK COLLECT
,它是我的实际代码的简化版本,它从实际表中执行 SELECT
。
我的最终目标是使用 UNION ALL
允许我将值附加到我的关联数组,而不是在执行一系列 SELECT
语句时替换它。像这样:
SELECT *
BULK COLLECT INTO l_tTest
FROM (SELECT t.StartDate, t.EndDate
FROM TABLE(l_tTest) t
UNION ALL
SELECT to_date('01/01/2011', 'MM/DD/YYYY'), to_date('01/01/2019', 'MM/DD/YYYY')
FROM DUAL);
如果您能提供任何帮助,我将不胜感激。
当您使用时似乎:
SELECT ...
BULK COLLECT INTO array
FROM ...
那么首先发生的事情就是array
你BULK COLLECT INTO
被重新初始化为一个空数组
因此,当您想在 table 集合表达式中使用它时,它已经是空的,不会生成任何行。
相反,您可以使用非关联数组并在 PL/SQL:
中使用 MULTISET
运算符
CREATE OR REPLACE PACKAGE table_test
IS
TYPE range IS RECORD
(
StartDate DATE,
EndDate DATE
);
TYPE range_table IS TABLE OF range
--INDEX BY PLS_INTEGER
;
END;
/
DECLARE
l_ranges table_test.range_table := table_test.range_table();
l_ranges2 table_test.range_table := table_test.range_table();
PROCEDURE output_ranges(
range_array table_test.range_table
)
IS
idx PLS_INTEGER;
BEGIN
dbms_output.put_line('Table Size: '||range_array.COUNT);
idx := range_array.FIRST;
LOOP
EXIT WHEN idx IS NULL;
dbms_output.put_line(
idx||': '||range_array(idx).StartDate||' - '||range_array(idx).EndDate
);
idx := range_array.NEXT(idx);
END LOOP;
END output_ranges;
BEGIN
l_ranges.EXTEND(2);
l_ranges(1) := table_test.range(DATE '2000-01-01', DATE '2001-01-01');
l_ranges(2) := table_test.range(DATE '2001-01-01', DATE '2002-01-01');
l_ranges2.EXTEND(2);
l_ranges2(1) := table_test.range(DATE '2002-01-01', DATE '2003-01-01');
l_ranges2(2) := table_test.range(DATE '2003-01-01', DATE '2004-01-01');
output_ranges(l_ranges);
output_ranges(l_ranges2);
l_ranges := l_ranges MULTISET UNION ALL l_ranges2;
output_ranges(l_ranges);
END;
/
输出:
Table Size: 2
1: 01-JAN-00 - 01-JAN-01
2: 01-JAN-01 - 01-JAN-02
Table Size: 2
1: 01-JAN-02 - 01-JAN-03
2: 01-JAN-03 - 01-JAN-04
Table Size: 4
1: 01-JAN-00 - 01-JAN-01
2: 01-JAN-01 - 01-JAN-02
3: 01-JAN-02 - 01-JAN-03
4: 01-JAN-03 - 01-JAN-04
我似乎在使用关联数组中的 Table 集合表达式到 select 时遇到问题(注意:我使用的是 Oracle 12c,所以这是允许的:Oracle Documentation)
举下面这个“简单”的例子:
首先,创建一个声明记录和关联数组的包:
CREATE OR REPLACE PACKAGE table_test
IS
TYPE pt_DateSpan IS RECORD
(
StartDate DATE,
EndDate DATE
);
TYPE pt_DateSpanTable IS TABLE OF pt_DateSpan INDEX BY PLS_INTEGER;
END;
/
然后,我编写了以下匿名块来测试功能:
DECLARE
l_tTest table_test.pt_DateSpanTable;
PROCEDURE lp_outputAArray (p_aaInput table_test.pt_DateSpanTable) IS
l_nTableSize INTEGER;
BEGIN
--I know I can use p_aaInput.COUNT, but I want to select using TABLE() to show that the functionality "works"
SELECT COUNT(*)
INTO l_nTableSize
FROM TABLE(p_aaInput);
dbms_output.put_line('Table Size: '||l_nTableSize);
FOR i IN 1..p_aaInput.COUNT LOOP
dbms_output.put_line(i||': '||to_char(p_aaInput(i).StartDate, 'MM/DD/YYYY')||' - '||to_char(p_aaInput(i).EndDate, 'MM/DD/YYYY'));
END LOOP;
END lp_outputAArray;
BEGIN
--ADD RECORD TO ASSOCIATIVE ARRAY
SELECT to_date('01/01/2000', 'MM/DD/YYYY'), to_date('01/01/2010', 'MM/DD/YYYY')
BULK COLLECT INTO l_tTest
FROM DUAL;
lp_outputAArray(l_tTest);
--SELECT THE ASSOCIATIVE ARRAY INTO ITSELF
SELECT t.StartDate, t.EndDate
BULK COLLECT INTO l_tTest
FROM TABLE(l_tTest) t;
lp_outputAArray(l_tTest);
END;
/
此块产生以下输出:
Table Size: 1
1: 01/01/2000 - 01/01/2010
Table Size: 0
我的问题是为什么第二个输出与第一个不一样?
另外,我意识到我不需要在这个例子的大部分中使用 BULK COLLECT
,它是我的实际代码的简化版本,它从实际表中执行 SELECT
。
我的最终目标是使用 UNION ALL
允许我将值附加到我的关联数组,而不是在执行一系列 SELECT
语句时替换它。像这样:
SELECT *
BULK COLLECT INTO l_tTest
FROM (SELECT t.StartDate, t.EndDate
FROM TABLE(l_tTest) t
UNION ALL
SELECT to_date('01/01/2011', 'MM/DD/YYYY'), to_date('01/01/2019', 'MM/DD/YYYY')
FROM DUAL);
如果您能提供任何帮助,我将不胜感激。
当您使用时似乎:
SELECT ...
BULK COLLECT INTO array
FROM ...
那么首先发生的事情就是array
你BULK COLLECT INTO
被重新初始化为一个空数组
因此,当您想在 table 集合表达式中使用它时,它已经是空的,不会生成任何行。
相反,您可以使用非关联数组并在 PL/SQL:
中使用MULTISET
运算符
CREATE OR REPLACE PACKAGE table_test
IS
TYPE range IS RECORD
(
StartDate DATE,
EndDate DATE
);
TYPE range_table IS TABLE OF range
--INDEX BY PLS_INTEGER
;
END;
/
DECLARE
l_ranges table_test.range_table := table_test.range_table();
l_ranges2 table_test.range_table := table_test.range_table();
PROCEDURE output_ranges(
range_array table_test.range_table
)
IS
idx PLS_INTEGER;
BEGIN
dbms_output.put_line('Table Size: '||range_array.COUNT);
idx := range_array.FIRST;
LOOP
EXIT WHEN idx IS NULL;
dbms_output.put_line(
idx||': '||range_array(idx).StartDate||' - '||range_array(idx).EndDate
);
idx := range_array.NEXT(idx);
END LOOP;
END output_ranges;
BEGIN
l_ranges.EXTEND(2);
l_ranges(1) := table_test.range(DATE '2000-01-01', DATE '2001-01-01');
l_ranges(2) := table_test.range(DATE '2001-01-01', DATE '2002-01-01');
l_ranges2.EXTEND(2);
l_ranges2(1) := table_test.range(DATE '2002-01-01', DATE '2003-01-01');
l_ranges2(2) := table_test.range(DATE '2003-01-01', DATE '2004-01-01');
output_ranges(l_ranges);
output_ranges(l_ranges2);
l_ranges := l_ranges MULTISET UNION ALL l_ranges2;
output_ranges(l_ranges);
END;
/
输出:
Table Size: 2 1: 01-JAN-00 - 01-JAN-01 2: 01-JAN-01 - 01-JAN-02 Table Size: 2 1: 01-JAN-02 - 01-JAN-03 2: 01-JAN-03 - 01-JAN-04 Table Size: 4 1: 01-JAN-00 - 01-JAN-01 2: 01-JAN-01 - 01-JAN-02 3: 01-JAN-02 - 01-JAN-03 4: 01-JAN-03 - 01-JAN-04