我是 PL/sql 的新手,我目前正在编写一些必须从两个表中提取数据的 PL/SQL 代码。到目前为止,我拥有的代码不断收到错误 PLS-00103:在期望其中一个时遇到符号“RETURN” 以下: * & = - + ;
at in 是 mod 余数不是 rem这是我目前的代码
CREATE OR REPLACE FUNCTION LISTNATION(N_NAME in VARCHAR2, R_NAME IN VARCHAR2, R_REGIONKEY IN NUMBER)
2 RETURN VARCHAR2 IS
3 R_REGIONKEY NUMBER(3);
4 R_NAME VARCHAR2(50);
5 N_NAME VARCHAR2(50);
6
7 BEGIN
8 select r_regionkey, r_name, n_name
9 from region
10 inner join nation
11 on r_regionkey = n_regionkey;
12
13 dbms_output.put_line = (R_REGIONKEY || ' ' || R_NAME || ':' || N_NAME || ',')
14
15 END;
16 /
答案 0 :(得分:1)
您收到错误的直接原因(在问题的原始版本中)是您在第 4 行末尾缺少分号。
但还有很多其他问题:
"
而不是单引号 '
。这些用于标识符,而不是字符串。where
子句,因此它将查找所有区域的数据。dbms_output
调用;它缺少一个右括号(同样,在原始问题中)并且不应该包含 =
。test
,但尚未声明。因此,要让函数使用 dbms_output
来显示结果 - 这依赖于调用者处理该输出,您不应该假设 - 您可以这样做:
CREATE OR REPLACE FUNCTION LISTNATION(P_R_REGIONKEY IN NUMBER)
RETURN VARCHAR2 IS
L_R_NAME REGION.R_NAME%TYPE;
L_N_NAME NATION.N_NAME%TYPE;
BEGIN
FOR l_row IN (
select r.r_name, n.n_name
from region r
inner join nation n
on r.r_regionkey = n.n_regionkey
where r.r_regionkey = p_r_regionkey
) LOOP
dbms_output.put_line (P_R_REGIONKEY || ' ' || l_row.R_NAME || ':' || l_row.N_NAME);
END LOOP;
RETURN 'test';
END;
/
这会为您的查询添加一个过滤器,将其转换为隐式游标,并循环遍历结果。
db<>fiddle 带有一些虚构的数据,表名和列名取自您的尝试。
不清楚你真正想要返回什么;您可能需要一个以逗号分隔的国家名称列表,在这种情况下,请查看 the listagg()
function。例如,您可以执行以下操作:
CREATE OR REPLACE FUNCTION LISTNATION(P_R_REGIONKEY IN NUMBER)
RETURN VARCHAR2 IS
L_RESULT VARCHAR2(4000);
BEGIN
select listagg(n.n_name, ',') within group (order by n.n_name)
into l_result
from region r
inner join nation n
on r.r_regionkey = n.n_regionkey
where r.r_regionkey = p_r_regionkey;
RETURN l_result;
END;
/
然后你可以调用它来获取单个值列表。
尽管在该查询周围使用 PL/SQL 函数包装器似乎不是很有用。大概这是一个练习...
无论如何要显示它,以便在列出所有国家时只显示区域键和区域一次?
您可以更改第二个函数以包含区域信息,将其与 listagg 结果连接起来:
CREATE OR REPLACE FUNCTION LISTNATION(P_R_REGIONKEY IN NUMBER)
RETURN VARCHAR2 IS
L_RESULT VARCHAR2(4000);
BEGIN
select r.r_regionkey || ' ' || r.r_name || ': '
|| listagg(n.n_name, ',') within group (order by n.n_name)
into l_result
from region r
inner join nation n
on r.r_regionkey = n.n_regionkey
where r.r_regionkey = p_r_regionkey
group by r.r_regionkey, r.r_name;
RETURN l_result;
END;
/
然后为您感兴趣的每个区域键调用它。
您的措辞方式听起来好像您不想传递区域键,而是想一次查看所有区域;并想使用 dbms_output
,这并不理想;并且真的不想返回任何东西。因此,您可以改用过程,更改游标查询以恢复区域名称,然后在循环内的 put_line
调用中进行连接:
CREATE OR REPLACE PROCEDURE LISTNATION IS
BEGIN
FOR l_row IN (
select r.r_regionkey, r.r_name,
listagg(n.n_name, ',') within group (order by n.n_name) as names
from region r
inner join nation n
on r.r_regionkey = n.n_regionkey
group by r.r_regionkey, r.r_name
order by r.r_regionkey
) LOOP
dbms_output.put_line (l_row.R_REGIONKEY || ' ' || l_row.R_NAME || ': ' || l_row.names);
END LOOP;
END;
/
dbms_output:
1 EMEA: FRANCE,UNITED KINGDOM
2 APAC: CHINA
当然有很多变化,这完全取决于您想要发生的情况,但您应该能够适应其中一种方法。另一种方法是让函数或过程生成引用游标,但同样不清楚您想要什么。但是使用 dbms_output
并不是一个好主意,因为调用者可能没有使用查找和显示它的客户端。