我正在尝试在PL / SQL中编写一个函数nbrJobs()
来计算用户过去曾经拥有的作业数。
为了做到这一点,我首先需要确定“员工ID”,这可以通过一对(名字,姓氏)确定。
当函数的参数为:
时,我设法做到这一点nbrJobs(firstName IN VARCHAR2(20), lastName IN VARCHAR2(25))
然后,这个简单的测试运行没有任何问题:
DECLARE
nbrJobsTotal NUMBER;
BEGIN
SELECT nbrJobs(first_name, last_name) INTO nbrJobsTotal
FROM employees
WHERE employee_id = 101
END
现在,问题是我的功能也应该适用于那种呼叫:
SELECT nbrJobs(first_name, last_name) INTO nbrJobsTotal FROM employees
表employees
包含多个元组。
所以,现在我对输入参数类型感到困惑。我应该使用VARRAY
,嵌套TABLE
,CURSOR
,还有其他什么?
如果选择了多行,SELECT
实际返回了什么?
答案 0 :(得分:3)
对SELECT
语句的每一行执行PL / SQL函数。因此,如果您在常规SELECT
SQL语句中调用函数,您将获得每条记录的值。
以下是将名字和姓氏连在一起的示例:
CREATE OR REPLACE FUNCTION NAME (p_FIRST_NAME IN VARCHAR2, p_LAST_NAME IN VARCHAR2)
RETURN VARCHAR2
AS
BEGIN
RETURN p_FIRST_NAME || ' ' || p_LAST_NAME;
END;
/
SELECT first_name, last_name, name(first_name, last_name) FROM HR.employees;
FIRST_NAME LAST_NAME NAME(FIRST_NAME,LAST_NAME)
---------- --------- --------------------------
Ellen Abel Ellen Abel
Sundar Ande Sundar Ande
Mozhe Atkinson Mozhe Atkinson
David Austin David Austin
如您所见,对于每一行执行PL / SQL函数并连接名字和姓氏,然后将结果作为新列返回到SELECT
语句。您无需更改函数以使其适用于多行。
现在,您将如何使用上面使用的SELECT语句在PL / SQL中执行此操作。您将需要使用游标循环结果,或者如果您只想将所有行的结果提取到变量中,则可以使用集合类型。
使用光标( 我在上面的例子中使用Cursor FOR LOOP)来证明这一点:
BEGIN
FOR result IN (SELECT first_name, last_name, name(first_name, last_name) name FROM HR.employees) LOOP
DBMS_OUTPUT.PUT_LINE(result.first_name || ', ' || result.last_name || ', ' || result.name);
END LOOP;
END;
/
Ellen, Abel, Ellen Abel
Sundar, Ande, Sundar Ande
Mozhe, Atkinson, Mozhe Atkinson
David, Austin, David Austin
这里发生的是我执行完全相同的SELECT
语句,但现在在Cursor FOR LOOP中,它允许我遍历已经返回的每一行。在这种情况下,我只是将结果打印到控制台中。
如果您只想将所有行保存到变量中,则必须使用PL/SQL Collection:
DECLARE
-- Specify cursor with expected results
CURSOR c1 IS
SELECT first_name, last_name, name(first_name, last_name) name
FROM HR.employees;
-- Create PL/SQL type for a nested table of the rowtype of the cursor (first_name, last_name, name)
TYPE NameSet IS TABLE OF c1%ROWTYPE;
employees NameSet; -- Instantiate a variable of the nested table of records
BEGIN
-- Assign values to nested table of records:
SELECT first_name, last_name, name(first_name, last_name) name
BULK COLLECT INTO employees
FROM HR.employees;
-- Print nested table of records:
FOR i IN employees.FIRST .. employees.LAST LOOP
DBMS_OUTPUT.PUT_LINE (
employees(i).first_name || ' ' ||
employees(i).last_name || ', ' ||
employees(i).name
);
END LOOP;
END;
/
Ellen Abel, Ellen Abel
Sundar Ande, Sundar Ande
Mozhe Atkinson, Mozhe Atkinson
David Austin, David Austin
正如您在此处看到的那样,SELECT
已执行,但我们在这里使用BULK COLLECT INTO
而非INTO
。这是因为SELECT
返回多行,因此我们需要告诉编译器我们确实期望这样做,以便编译器不会抛出更多行返回的错误。
最后但并非最不重要的是,鉴于您在上面的示例nbrJobsTotal
中使用变量名称SELECT nbrJobs(first_name, last_name) INTO nbrJobsTotal FROM employees
,我认为您真正想要尝试做的是总结所有不同的数量员工在贵公司工作的工作。你可以做到这一点,但使用内置的SUM()
函数,它是一个聚合函数,即它只返回一行没有GOUP BY
子句:
SELECT SUM(nbrJobs(first_name, last_name)) INTO nbrJobsTotal FROM employees
答案 1 :(得分:1)
您可以使用Table of
Type
- bulk collect
select
语句返回的所有行。
根据您的示例,它看起来像这样:
DECLARE
nbrJobsTotal NUMBER;
TYPE jobsTotalTable_type IS TABLE OF nbrJobsTotal%TYPE;
jobsTotalTable jobsTotalTable_type ;
BEGIN
--bulk collect results
SELECT nbrJobs(first_name, last_name) BULK COLLECT INTO jobsTotalTable
FROM employees;
--print results
FOR indx IN 1 .. jobsTotalTable.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(jobsTotalTable (indx));
END LOOP;
END