CREATE or REPLACE PROCEDURE TEST(
activationStartDate IN DATE,
activationEndDate IN DATE,
deActivationStartDate IN DATE,
deActivationEndDate IN DATE
)
AS
FirstNameListTable LIST_TABLE;
{--COMMENT :LIST_TABLE is nested table :create or replace TYPE "LIST_TABLE" as table of varchar2(20);-----Nested Table Declaration
/
}
totalSameFirstName NUMBER;
j NUMBER := 1;
BEGIN
SELECT first_name BULK COLLECT INTO FirstNameListTable FROM Employee where start_date between activationStartDate AND activationEndDate
MINUS
SELECT first_name FROM Employee where start_date between deActivationStartDate AND deActivationEndDate
FOR i IN FirstNameListTable.FIRST .. FirstNameListTable.LAST LOOP
SELECT count(*) INTO totalSameFirstName FROM Employee where start_date between activationStartDate AND activationEndDate AND first_name=FirstNameListTable(i)
IF totalSameFirstName > 2 THEN
---business logic
END IF;
END LOOP;
实际上上面有两个查询
将此查询视为Q1:
SELECT first_name BULK COLLECT INTO FirstNameListTable FROM Employee where start_date between activationStartDate AND activationEndDate
MINUS
SELECT first_name FROM Employee where start_date between deActivationStartDate AND deActivationEndDate
此查询为Q2:
SELECT count(*) INTO totalSameFirstName FROM Employee where start_date between activationStartDate AND activationEndDate AND first_name=FirstNameListTable(i)
在两个qyery我扫描完整表,我认为没有必要。我正在迭代Q1的结果,然后再次扫描表来计算类似的first_name。如果特定的firstName出现两次以上我编写业务逻辑。
我可以将两个查询组合起来,意味着我想在一些PL / SQL数据结构中存储Q1的结果,并希望在Q1的结果上执行Q2。
我想将Q1修改为
SELECT * BULK COLLECT INTO FirstNameListTable FROM Employee where start_date between activationStartDate AND activationEndDate
MINUS
SELECT * FROM Employee where start_date between deActivationStartDate AND deActivationEndDate
但是如何在pl / sql dataStructure中存储'select *'结果以及如何将这些记录传递给第二个查询。你能告诉我我的代码会是什么样子的吗? 试着更清楚,我在这个PL / SQL中缺乏想法,即使它听起来像一个经典:我花了好几个小时试图玩这个但却无处可去
@Ollie 我按照你的建议更改了代码但是遇到了一些错误并且无法解决它们
CREATE or REPLACE PROCEDURE TEST(
activationStartDate IN DATE,
activationEndDate IN DATE,
deActivationStartDate IN DATE,
deActivationEndDate IN DATE,
Out_Entity OUT TEST1.RefCsr
)
AS
FirstNameListTable CRITERIA_LIST_TABLE;
out NUMBER;
j NUMBER := 1;
CURSOR main_cur
IS
WITH include_rec
AS (SELECT first_name,COUNT(1) OVER (PARTITION BY first_name) name_count FROM employee where start_date between activationStartDate AND activationEndDate
MINUS
SELECT first_name FROM employee where start_date between deActivationStartDate AND deActivationEndDate)
SELECT first_name FROM include_rec WHERE name_count > 2;
BEGIN
OPEN main_cur;
FETCH main_cur BULK COLLECT INTO FirstNameListTable;
CLOSE main_cur;
OPEN Out_Entity FOR SELECT * FROM TABLE(
CAST (
FirstNameListTable AS LIST_TABLE
)
) Nos;
END;
/
错误1:PL / SQL:忽略SQL语句{表示:“WITH include_rec”行} 错误2:PL / SQL:ORA-01789:查询块的结果列数不正确{指示行:“AS(SELECT first_name,COUNT(1)OVER(PARTITION BY first_name)”} 提前致谢 等待你的回复
答案 0 :(得分:0)
我想告诉我,我没有太多时间来处理这个问题,所以可能会有一些错误,但它应该给你一个我想告诉你的要点:
CREATE or REPLACE
PROCEDURE TEST(
activationStartDate IN DATE,
activationEndDate IN DATE,
deActivationStartDate IN DATE,
deActivationEndDate IN DATE )
AS
CURSOR main_cur
IS
WITH include_rec
AS (SELECT first_name,
start_date,
COUNT(1) OVER (PARTITION BY first_name) name_count
FROM Employee
WHERE start_date BETWEEN activationStartDate
AND activationEndDate)
SELECT DISTINCT
first_name
FROM include_rec
WHERE start_date NOT BETWEEN deActivationStartDate
AND deActivationEndDate
AND name_count > 2;
--
FirstNameListTable dbms_sql.varchar2_table;
BEGIN
OPEN main_cur;
FETCH main_cur BULK COLLECT INTO FirstNameListTable;
CLOSE main_cur;
FOR i IN FirstNameListTable.FIRST .. FirstNameListTable.LAST
LOOP
---business logic
END LOOP;
etc...
我还会说,如果你期望一个大的结果集,那么也可以把BULK COLLECT放到一个循环中来减少你的内存需求。
在理想的世界中,您将变量activationStartDate,activationEndDate,deActivationStartDate和deActivationEndDate作为游标参数传递给游标,以保持游标模块化,但这取决于您。 ; - )
希望这会有所帮助...... 奥利。
编辑: 在回答有关使用记录从表中选择*的问题时,您可以根据游标列声明一个关联数组,对于上面的示例,如果您想从EMPLOYEE中选择多个列,那么在您选择的WITH子句之后来自EMPLOYEE的命名列,而不是:
FirstNameListTable dbms_sql.varchar2_table;
将关联数组类型和变量声明为:
TYPE main_cur_tabtype IS TABLE OF main_cur%ROWTYPE
INDEX BY PLS_INTEGER;
main_cur_tab main_cur_tabtype;
这为您提供了一个灵活的数组,可以自动保存光标中选择的列(main_cur)。
您可以使用BULK COLLECT将记录收集到此数组中:
OPEN main_cur;
FETCH main_cur BULK COLLECT INTO main_cur_tab;
CLOSE main_cur;
并通过以下方式循环播放:
FOR i IN main_cur_tab.FIRST .. main_cur_tab.LAST
LOOP
etc.
至于将结果集返回给Java,我不是java专家,您需要在其他论坛中询问或使用Java标记标记此问题,并希望Java人员选择并为您解答
答案 1 :(得分:0)
你能在SQL中做到这一点吗? 例如。也许像这样使用WITH:
WITH q1 AS (SELECT ....)
SELECT /* q2 */ ... FROM q1
WHERE ..
GROUP BY etc
如果您可以在SQL中执行此操作,则可以在以后随时将其嵌入到PL / SQL中。